R Select()، Filter()، Arrange()، خط الأنابيب مع المثال

⚡ ملخص ذكي

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

  • 📋 اختيار العمود: يُبقي الأمر select(df, A, B) على الأعمدة المسماة، بينما يُبقي الأمر select(df, A:C) على نطاق، ويُسقط الأمر select(df, -C) أحدها.
  • 🔎 تصفية الصفوف: تقوم الدالة filter(df, condition) بمطابقة الصفوف، وتتحد الشروط مع علامة العطف (&) لـ AND أو الخط العمودي لـ OR.
  • 🔣 فرز: تقوم الدالة arrange() بترتيب الصفوف تصاعديًا بشكل افتراضي، وتقوم الدالة desc() بعكس أي عمود واحد.
  • 🔗 أنبوب Operaتور: يقوم عامل التشغيل %>% بتمرير كل نتيجة مباشرة إلى الفعل التالي، لذلك لا توجد كائنات وسيطة تشوش البيئة.
  • 🧹 وظائف مساعدة: تقوم الدوال starts_with() و contains() و where() بتحديد الأعمدة حسب النمط أو النوع بدلاً من الاسم.
  • 📐 ترتيب الأفعال مهم: قم بالتصفية مبكراً لتقليص حجم البيانات، ثم حددها، ثم رتبها، مما يجعل كل خطوة لاحقة أرخص.

حدد R تصفية ترتيب خط الأنابيب

ما هو 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

الأسئلة الشائعة

تأتي دالة magrittr %>% مُدمجة مع مكتبة dplyr وتدعم صيغة العناصر النائبة باستخدام النقطة. أما دالة |> الأصلية فقد أُضيفت في الإصدار 4.1 من R ولا تحتاج إلى أي حزمة. كلتاهما تُمرّران النتيجة من اليسار إلى الوسيط الأول في اليمين.

لا. كل عملية dplyr تُعيد إطار بيانات جديدًا وتترك المدخلات دون تغيير. يجب عليك إسناد النتيجة إلى كائن، أو تمريرها عبر الأنابيب، حتى يستمر التغيير.

تُرجع المقارنة مع NA القيمة NA بدلاً من TRUE، وتحتفظ الدالة filter() فقط بالصفوف التي قيمتها TRUE. استخدم الدالة is.na() لاختيار القيم المفقودة عمدًا، أو استخدم الدالة drop_na() من tidyr لإزالتها.

تعتمد هندسة الميزات لنماذج الذكاء الاصطناعي في الغالب على تصفية الصفوف، واختيار الأعمدة، والفرز. يُعبّر dplyr عن هذه الخطوات في شكل مسارات قابلة للقراءة يمكن للمراجعين تدقيقها، وهو أمر بالغ الأهمية عندما يكون من الضروري أن تكون مجموعة بيانات التدريب قابلة للتكرار.

نعم. يمكن للمساعدين المدعومين بالذكاء الاصطناعي ترجمة عملية تحديد نطاق الأقواس إلى استدعاءات select() و filter() وشرح آلية عمل الأنابيب. يُنصح دائمًا بتشغيل كلا الإصدارين ومقارنة الأبعاد، لأن لغة R الأساسية و dplyr تتعاملان مع القيم المفقودة بشكل مختلف.

تلخيص هذه التدوينة بـ: