R Select()، Filter()، Arrange()، خط الأنابيب مع المثال
⚡ ملخص ذكي
تُعدّ دوال Select وFilter وArrange في لغة R ثلاث دوال من مكتبة dplyr تُستخدم لتقليص إطار البيانات إلى الأعمدة والصفوف والترتيب المطلوب. يشرح هذا الدليل كيفية ربط هذه الدوال باستخدام عامل الربط (pipe operator) على مجموعة بيانات لأوقات السفر مكونة من 205 صفوف.

ما هو dplyr في لغة R؟
com.dplyr هي حزمة معالجة البيانات الخاصة بـ tidyverse. وهي تحل محل صيغة الأقواس في base R باستخدام مجموعة صغيرة من الأفعال، يُسمى كل منها باسم الفعل الذي يقوم به، ويأخذ كل منها إطار البيانات كمعامله الأول. هذا الشكل المتسق هو ما يسمح بربط الأفعال معًا.
| الفعل | يتصرف على | ماذا يفعل |
|---|---|---|
| تحديد() | الأعمدة | يحتفظ بالمتغيرات أو يحذفها |
| منقي() | الصفوف | يحافظ على الصفوف المطابقة لشرط معين |
| يرتب() | الصفوف | يعيد ترتيب الصفوف حسب عمود واحد أو أكثر |
| متحور () | الأعمدة | يقوم بإنشاء أو تعديل متغير |
| ملخص() | الطاولة بأكملها | يدمج العديد من الصفوف في إحصائية واحدة |
| group_by() | الطاولة بأكملها | يقسم البيانات بحيث يتم تشغيل الأفعال اللاحقة لكل مجموعة |
يشرح هذا الدرس الأفعال الثلاثة الأولى بالإضافة إلى فعل الأنبوب. شرح وظائف التجميع يغطي هذا التقرير وظيفة group_by() ووظيفة summarise() بالتفصيل.
مجموعة البيانات المستخدمة في هذا البرنامج التعليمي
تحتوي مكتبة dplyr على دوال مفيدة للتنقل داخل مجموعة البيانات. ستستخدم في هذا الدرس مجموعة بيانات أوقات السفر، التي تسجل رحلات السائق بين المنزل ومكان العمل. تتضمن مجموعة البيانات أربعة عشر متغيرًا، منها:
- DayOfWeek: تحديد اليوم من الأسبوع الذي يستخدم فيه السائق سيارته
- المسافة: المسافة الإجمالية للرحلة
- MaxSpeed: السرعة القصوى للرحلة
- الوقت الإجمالي: طول الرحلة بالدقائق
تحتوي مجموعة البيانات على 205 مشاهدة، وقد جرت الرحلات من Monday إلى الجمعة.
أولا وقبل كل شيء، تحتاج إلى:
- تحميل مجموعة البيانات
- التحقق من بنية البيانات.
إحدى وظائف dplyr المفيدة هي glimpse(). تؤدي نفس وظيفة str() الأساسية في R ولكنها تطبع صفًا واحدًا لكل متغير مع نوعه والقيم القليلة الأولى، مما يسهل عملية المسح بشكل كبير على مجموعة بيانات واسعة.
library(dplyr) PATH <- "https://raw.githubusercontent.com/guru99-edu/R-Programming/master/travel_times.csv" df <- read.csv(PATH) glimpse(df)
الإخراج:
## Observations: 205 ## Variables: 14 ## $ X <int> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, ... ## $ Date <fctr> 1/6/2012, 1/6/2012, 1/4/2012, 1/4/2012, 1/3/20... ## $ StartTime <fctr> 16:37, 08:20, 16:17, 07:53, 18:57, 07:57, 17:3... ## $ DayOfWeek <fctr> Friday, Friday, Wednesday, Wednesday, Tuesday,... ## $ GoingTo <fctr> Home, GSK, Home, GSK, Home, GSK, Home, GSK, GS... ## $ Distance <dbl> 51.29, 51.63, 51.27, 49.17, 51.15, 51.80, 51.37... ## $ MaxSpeed <dbl> 127.4, 130.3, 127.4, 132.3, 136.2, 135.8, 123.2... ## $ AvgSpeed <dbl> 78.3, 81.8, 82.0, 74.2, 83.4, 84.5, 82.9, 77.5,... ## $ AvgMovingSpeed <dbl> 84.8, 88.9, 85.8, 82.9, 88.1, 88.8, 87.3, 85.9,... ## $ FuelEconomy <fctr> , , , , , , -, -, 8.89, 8.89, 8.89, 8.89, 8.89... ## $ TotalTime <dbl> 39.3, 37.9, 37.5, 39.8, 36.8, 36.8, 37.2, 37.9,... ## $ MovingTime <dbl> 36.3, 34.9, 35.9, 35.6, 34.8, 35.0, 35.3, 34.3,... ## $ Take407All <fctr> No, No, No, No, No, No, No, No, No, No, No, No... ## $ Comments <fctr> , , , , , , , , , , , , , , , Put snow tires o...
من الواضح أن متغير التعليقات يحتاج إلى نظرة فاحصة: جميع الملاحظات الأولى فارغة.
sum(df$Comments =="")
Code تفسير
- sum(df$Comments == “”): احسب عدد المشاهدات التي تساوي سلسلة نصية فارغة في عمود التعليقات (Comments) في إطار البيانات df
الإخراج:
## [1] 181
بعد تحميل البيانات، ابدأ بالفعل الذي يقوم بتقليص الأعمدة.
تحديد()
سنبدأ مع الفعل Select(). لا نحتاج بالضرورة إلى جميع المتغيرات، ومن الممارسات الجيدة أن تختار فقط المتغيرات التي تجدها ذات صلة.
لدينا 181 ملاحظة مفقودة، أي ما يقرب من 90% من مجموعة البيانات. إذا قررت استبعادهم، فلن تتمكن من مواصلة التحليل.
الاحتمال الآخر هو إسقاط المتغير Comment باستخدام الفعل Select() .
يمكننا تحديد المتغيرات بطرق مختلفة باستخدام التحديد (). لاحظ أن الوسيطة الأولى هي مجموعة البيانات.
- `select(df, A, B ,C)`: Select the variables A, B and C from df dataset. - `select(df, A:C)`: Select all variables from A to C from df dataset. - `select(df, -C)`: Exclude C from the dataset from df dataset.
يمكنك استخدام الطريقة الثالثة لاستبعاد متغير التعليقات.
step_1_df <- select(df, -Comments) dim(df)
الإخراج:
## [1] 205 14
dim(step_1_df)
الإخراج:
## [1] 205 13
تحتوي مجموعة البيانات الأصلية على 14 ميزة بينما تحتوي step_1_df على 13.
دوال مساعدة select() في لغة R
يصبح تسمية كل عمود أمرًا غير عملي عندما تحتوي مجموعة البيانات على عشرات المتغيرات. يوفر dplyr أدوات مساعدة لاختيار الأعمدة حسب النمط أو النوع بدلاً من ذلك.
| المساعد | يحدد الأعمدة التي | مثال |
|---|---|---|
| يبدأ_بـ() | ابدأ بسلسلة | حدد (df، يبدأ_بـ(“Avg”)) |
| ينتهي بـ() | أنهِ بسلسلة نصية | حدد (df، ينتهي بـ "الوقت")) |
| يتضمن() | يحتوي على سلسلة نصية في أي مكان | حدد(df، يحتوي("السرعة")) |
| اعواد الكبريت() | مطابقة تعبير نمطي | حدد (df، يطابق(“^Max|^Avg”)) |
| أين() | استيفاء اختبار النوع | حدد (df، حيث (is.numeric)) |
| كل شئ() | لم يتم تسميتهم بعد | حدد (df، TotalTime، كل شيء()) |
# Keep only the timing columns df %>% select(ends_with("Time")) # Keep every numeric column df %>% select(where(is.numeric)) # Move TotalTime to the front, keep the rest in place df %>% select(TotalTime, everything())
هناك فعلان آخران يتناسبان بشكل طبيعي مع دالة select(). استخدم rename(new_name = old_name) لإعادة تسمية عمود دون حذفه.ping أما البقية، و relocate() لنقل الأعمدة دون سردها جميعًا.
منقي()
يحتفظ الأمر filter() بالبيانات التي تحقق شرطًا معينًا. يعمل الأمر filter() تمامًا مثل الأمر select()، حيث يتم تمرير إطار البيانات أولًا ثم الشرط مفصولًا بفاصلة.
filter(df, condition)
arguments:
- df: dataset used to filter the data
- condition: Condition used to filter the data
معايير واحدة
أولًا، يمكنك حساب عدد الملاحظات ضمن كل مستوى لمتغير العامل.
table(step_1_df$GoingTo)
Code تفسير
- دالة table(): تحسب عدد المشاهدات لكل مستوى. وتتوقع متغيرًا من نوع عامل أو حرفي.
- جدول (step_1_df$GoingTo): احسب عدد الرحلات باتجاه كل وجهة
الإخراج:
## ## GSK Home ## 105 100
يشير جدول الوظائف () إلى أن 105 رحلة متجهة إلى GSK و100 رحلة إلى المنزل.
يمكننا تصفية البيانات لإرجاع مجموعة بيانات واحدة تحتوي على 105 ملاحظة وأخرى تحتوي على 100 ملاحظة.
# Select observations where GoingTo == Home select_home <- filter(df, GoingTo == "Home") dim(select_home)
الإخراج:
## [1] 100 14
# Select observations where GoingTo == GSK (work) select_work <- filter(df, GoingTo == "GSK") dim(select_work)
الإخراج:
## [1] 105 14
معايير متعددة
يمكننا تصفية مجموعة بيانات باستخدام أكثر من معيار واحد. على سبيل المثال، يمكنك...tracفي الملاحظات التي تكون فيها الوجهة هي المنزل وحدثت الرحلة يوم الأربعاء.
select_home_wed <- filter(df, GoingTo == "Home" & DayOfWeek == "Wednesday") dim(select_home_wed)
الإخراج:
## [1] 23 14
23 ملاحظة مطابقة لهذا المعيار.
الشروط الشائعة للتصفية () Operaتورس في ر
تحتفظ الدالة filter() بكل صف يتم فيه تقييم الشرط إلى TRUE. أما الصفوف التي يتم تقييمها إلى NA فتُحذف، وهو السلوك الذي يُفاجئ معظم المبتدئين.
| المُشغل | معنى | مثال |
|---|---|---|
| == | يساوي | filter(df, GoingTo == “Home”) |
| != | لا يساوي | filter(df, DayOfWeek != “Monday") |
| & | ويجب أن يحمل كلاهما | filter(df, Distance > 50 & MaxSpeed > 130) |
| | | أو، قد يكون أي منهما صحيحًا | filter(df, DayOfWeek == “Monday" | يوم الأسبوع == "الجمعة") |
| ٪في٪ | يطابق أي قيمة في متجه | filter(df, DayOfWeek %in% c(“Monday"، "جمعة")) |
| ما بين() | يقع ضمن نطاق رقمي | filter(df, between(Distance, 48, 52)) |
| is.na() | هل القيمة مفقودة؟ | filter(df, is.na(FuelEconomy)) |
ثلاث عادات تمنع معظم أخطاء دالة filter().
- استخدم %in% بدلاً من OR المتسلسلة. filter(df, DayOfWeek %in% c(“Monday"," "Friday")) أقصر وأصعب بكثير في الكتابة الخاطئة من مقارنتين == متصلتين بخط عمودي.
- لا تستخدم أبدًا علامة == لاختبار قيمة مفقودة. العبارة x == NA تُرجع القيمة NA، وليس TRUE، لذا يتم حذف الصف دون تنبيه. استخدم is.na(x) بدلاً من ذلك.
- الفواصل تعني "و". الدالة filter(df, a, b) مطابقة للدالة filter(df, a & b)، ولهذا السبب يعمل المثال السابق في هذا البرنامج التعليمي في كلتا الحالتين.
الأنبوب Operator in dplyr
يتطلب إنشاء مجموعة البيانات الكثير من العمليات، مثل:
- استيراد
- دمج
- اختيار
- تصفية
- وما إلى ذلك وهلم جرا
تأتي مكتبة dplyr مع عامل عملي، %>%، يسمى أنبوبفهو يجعل معالجة البيانات أكثر سلاسة وسرعة وأقل عرضة للخطأ.
هذا المشغل عبارة عن كود يقوم بتنفيذ الخطوات دون حفظ الخطوات الوسيطة على القرص الصلب. إذا عدت إلى مثالنا أعلاه، فيمكنك تحديد المتغيرات التي تهمك وتصفيتها. لدينا ثلاث خطوات:
- الخطوة 1: استيراد البيانات: استيراد بيانات نظام تحديد المواقع
- الخطوة 2: تحديد البيانات: حدد GoingTo وDayOfWeek
- الخطوة 3: تصفية البيانات: العودة إلى المنزل والأربعاء فقط
يمكننا استخدام الطريقة الصعبة للقيام بذلك:
# Step 1 step_1 <- read.csv(PATH) # Step 2 step_2 <- select(step_1, GoingTo, DayOfWeek) # Step 3 step_3 <- filter(step_2, GoingTo == "Home", DayOfWeek == "Wednesday") head(step_3)
الإخراج:
## GoingTo DayOfWeek ## 1 Home Wednesday ## 2 Home Wednesday ## 3 Home Wednesday ## 4 Home Wednesday ## 5 Home Wednesday ## 6 Home Wednesday
ليست هذه طريقة ملائمة لربط العديد من العمليات. تبقى كل نتيجة وسيطة في البيئة، وسرعان ما تفقد الأسماء معناها.
استخدم عامل الربط %>% بدلاً من ذلك. أنت تُسمّي إطار البيانات مرة واحدة في البداية، وكل خطوة تنطلق منه.
بناء الجملة الأساسي لخط الأنابيب
New_df <- df %>% step 1 %>% step 2 %>% ... arguments - New_df: Name of the new data frame - df: Data frame used to compute the step - step: Instruction for each step - Note: the last instruction does not need a trailing `%>%`, because nothing follows it - Note: assigning the result to a new object is optional. Without it, the output prints in the console.
يمكنك إنشاء الأنبوب الأول الخاص بك باتباع الخطوات المذكورة أعلاه.
# Create the data frame filter_home_wed.It will be the object return at the end of the pipeline filter_home_wed <- #Step 1 read.csv(PATH) %>% #Step 2 select(GoingTo, DayOfWeek) %>% #Step 3 filter(GoingTo == "Home",DayOfWeek == "Wednesday") identical(step_3, filter_home_wed)
الإخراج:
## [1] TRUE
الكائنان متطابقان، لذا أنتجت الأنبوبة نفس النتيجة تمامًا في عبارة واحدة قابلة للقراءة.
يرتب()
في خانة رمز الخصم، أدخل TABBYDAY. البرنامج التعليمي السابقستتعلم كيفية فرز القيم باستخدام الدالةsort(). مكتبة dplyr لها وظيفة الفرز الخاصة بها. إنه يعمل مثل السحر مع خط الأنابيب. يمكن للفعل الترتيبي () إعادة ترتيب صف واحد أو عدة صفوف، إما تصاعديًا (افتراضيًا) أو تنازليًا.
- `arrange(A)`: Ascending sort of variable A - `arrange(A, B)`: Ascending sort of variable A and B - `arrange(desc(A), B)`: Descending sort of variable A and ascending sort of B
يمكننا فرز المسافة حسب الوجهة.
# Sort by destination and distance step_2_df <- step_1_df %>% arrange(GoingTo, Distance) head(step_2_df)
الإخراج:
## X Date StartTime DayOfWeek GoingTo Distance MaxSpeed AvgSpeed ## 1 193 7/25/2011 08:06 Monday GSK 48.32 121.2 63.4 ## 2 196 7/21/2011 07:59 Thursday GSK 48.35 129.3 81.5 ## 3 198 7/20/2011 08:24 Wednesday GSK 48.50 125.8 75.7 ## 4 189 7/27/2011 08:15 Wednesday GSK 48.82 124.5 70.4 ## 5 95 10/11/2011 08:25 Tuesday GSK 48.94 130.8 85.7 ## 6 171 8/10/2011 08:13 Wednesday GSK 48.98 124.8 72.8 ## AvgMovingSpeed FuelEconomy TotalTime MovingTime Take407All ## 1 78.4 8.45 45.7 37.0 No ## 2 89.0 8.28 35.6 32.6 Yes ## 3 87.3 7.89 38.5 33.3 Yes ## 4 77.8 8.45 41.6 37.6 No ## 5 93.2 7.81 34.3 31.5 Yes ## 6 78.8 8.54 40.4 37.3 No
أفعال dplyr في لغة R: مرجع سريع
يسرد الجدول أدناه كل فعل مستخدم في هذا البرنامج التعليمي، مع صيغته وما يعيده كل استدعاء:
| الفعل | الهدف | Code | تفسير |
|---|---|---|---|
| لمحة | تحقق من بنية df |
glimpse(df)
|
نفس الغرض من str()، وأسهل في القراءة |
| تحديد() | تحديد/استبعاد المتغيرات |
select(df, A, B ,C)
|
حدد المتغيرات A وB وC |
select(df, A:C)
|
حدد جميع المتغيرات من A إلى C | ||
select(df, -C)
|
استبعاد ج | ||
| منقي() | احتفظ بالصفوف التي تطابق شرطًا واحدًا أو أكثر |
filter(df, condition1)
|
شرط واحد |
filter(df, condition1 & condition2)
|
شرطان مجتمعان مع "و" | ||
| يرتب() | قم بفرز مجموعة البيانات بمتغير واحد أو أكثر |
arrange(A)
|
النوع التصاعدي للمتغير A |
arrange(A, B)
|
النوع التصاعدي للمتغير A و B | ||
arrange(desc(A), B)
|
النوع التنازلي للمتغير A والنوع التصاعدي للمتغير B | ||
| %>% | إنشاء خط أنابيب بين كل خطوة |
step 1 %>% step 2 %>% step 3 |
