دمج إطارات البيانات في R: المطابقة الكاملة والجزئية

⚡ ملخص ذكي

تتيح عملية دمج إطارات البيانات في لغة R ربط جدولين بناءً على عمود مفتاح مشترك واحد أو أكثر. تغطي دالة merge() عمليات الربط الداخلي، والربط الأيسر، والربط الأيمن، والربط الكامل، ويوضح هذا الشرح كلاً من الربط الكامل والربط الجزئي.

  • 🔑 الأعمدة الرئيسية: تقوم الدالة merge() بالربط على أساس by، أو على أساس by.x و by.y عندما يحمل المفتاح اسمًا مختلفًا في كل إطار.
  • 🔗 المباراة الكاملة: يحتفظ الربط الداخلي الافتراضي فقط بالصفوف التي يظهر مفتاحها في كلا إطاري البيانات.
  • 🧩 المطابقة الجزئية: يؤدي تعيين all.x = TRUE إلى الاحتفاظ بكل صف من الإطار الأول وملء الفراغات بـ NA.
  • 📐 التحقق من الأبعاد: قم بمقارنة dim() قبل وبعد عملية الدمج لاكتشاف الصفوف المفقودة أو المكررة بواسطة عملية الربط.
  • ⚙️ التحكم في الانضمام: تحدد العلامات all و all.x و all.y السلوك الداخلي أو الأيسر أو الأيمن أو الخارجي الكامل.
  • 🛠️ البديل الحديث: يقوم dplyr بتسمية كل عملية ربط في الفعل نفسه ويحافظ على ترتيب الصفوف الأصلي.

دمج إطارات البيانات في R

في كثير من الأحيان، لدينا بيانات من مصادر متعددة. لإجراء التحليل، نحن بحاجة إلى دمج إطاري بيانات مع واحد أو أكثر المتغيرات الرئيسية المشتركة.

أنواع الدمج (الربط) في لغة R

قبل الخوض في الأمثلة، من المفيد معرفة أن الدالة merge() تُنفذ جميع أنواع الربط التي يتوقعها مستخدم SQL. ويتم التحكم في سلوكها من خلال الوسائط all و all.x و all.y، وليس من خلال اسم دالة مختلف.

نوع الانضمام صفوف محفوظة استدعاء دالة الدمج () مكافئ dplyr
الربط الداخلي (افتراضي) المفاتيح الموجودة فقط في كلا الإطارين merge(x, y, by = “k”) inner_join(x, y, by = “k”)
ترك صلة خارجية جميع صفوف x، NA حيث لا يوجد تطابق لـ y merge(x, y, by = “k”, all.x = TRUE) left_join(x, y, by = “k”)
الصلة الخارجية اليمنى جميع صفوف y، NA حيث لا يوجد تطابق لـ x merge(x, y, by = “k”, all.y = TRUE) right_join(x, y, by = “k”)
صلة خارجية كاملة كل صف من كلا الإطارين merge(x, y, by = “k”, all = TRUE) full_join(x, y, by = “k”)
تقاطع الانضمام كل مجموعة من الصفوف merge(x, y, by = NULL) cross_join(x, y)

هناك تفصيلان يجدر تذكرهما قبل المكالمة الأولى:

  • يؤدي حذف كلمة "by" إلى دمج R على كل اسم عمود مشترك بين الإطارين، وهو أمر نادرًا ما يكون ما تريده.
  • تقوم الدالة merge() بفرز النتيجة حسب عمود المفتاح؛ مرر sort = FALSE للحفاظ على الترتيب الوارد.

مباراة كاملة

تُعيد المطابقة الكاملة القيم التي لها نظير في جدول الوجهة فقط. أما الصفوف التي لا يوجد لها تطابق فتُحذف من إطار البيانات الجديد. في المقابل، تحتفظ المطابقة الجزئية بتلك الصفوف وتملأ الأعمدة المفقودة بقيم NA.

سوف نرى بسيطة الانضمام الداخلي. تحدد الكلمة الأساسية "الربط الداخلي" السجلات التي تحتوي على قيم متطابقة في كلا الجدولين. لضم مجموعتي بيانات، يمكننا استخدام وظيفة الدمج (). سنستخدم ثلاث حجج:

merge(x, y, by.x = x, by.y = y)

Arguments:
-x: The origin data frame
-y: The data frame to merge
-by.x: The column used for merging in x data frame. Column x to merge on
-by.y: The column used for merging in y data frame. Column y to merge on

على سبيل المثال:

إنشاء مجموعة البيانات الأولى مع المتغيرات

  • لقب
  • الجنسية

إنشاء مجموعة البيانات الثانية مع المتغيرات

  • لقب
  • أفلام

المتغير الرئيسي المشترك هو اسم العائلة. يمكننا دمج كليهما إطارات البيانات وتأكد من أن الأبعاد هي 7×3.

نضيف stringsAsFactors=FALSE في إطار البيانات لأننا لا نريد R لتحويل السلاسل إلى عامليجب أن يبقى المتغير عبارة عن متجه نصي. منذ الإصدار 4.0.0 من R، أصبح هذا هو الوضع الافتراضي للدالة data.frame()، لذا فإن الوسيط اختياري في الكود الجديد وغير ضار في الكود القديم.

# Create origin dataframe(

producers <- data.frame(   
    surname =  c("Spielberg","Scorsese","Hitchcock","Tarantino","Polanski"),    
    nationality = c("US","US","UK","US","Poland"),    
    stringsAsFactors=FALSE)

# Create destination dataframe
movies <- data.frame(    
    surname = c("Spielberg",
		"Scorsese",
                "Hitchcock",
              	"Hitchcock",
                "Spielberg",
                "Tarantino",
                "Polanski"),    
    title = c("Super 8",
    		"Taxi Driver",
    		"Psycho",
    		"North by Northwest",
    		"Catch Me If You Can",
    		"Reservoir Dogs","Chinatown"),                
     		stringsAsFactors=FALSE)

# Merge two datasets
m1 <- merge(producers, movies, by.x = "surname")
m1
dim(m1)

الإخراج:

surname		nationality		title
1 Hitchcock		UK		Psycho
2 Hitchcock		UK		North by Northwest
3 Polanski		Poland		Chinatown
4 Scorsese		US		Taxi Driver
5 Spielberg		US		Super 8
6 Spielberg		US		Catch Me If You Can
7 Tarantino		US		Reservoir Dogs

لنقم بدمج إطارات البيانات عندما يكون للمتغيرات الرئيسية المشتركة أسماء مختلفة.

نقوم بتغيير اللقب إلى الاسم في إطار بيانات الأفلام. نستخدم الدالة المتطابقة (x1, x2) للتحقق مما إذا كان كلا إطاري البيانات متطابقين.

# Change name of ` movies ` dataframe
colnames(movies)[colnames(movies) == 'surname'] <- 'name'
# Merge with different key value
m2 <- merge(producers, movies, by.x = "surname", by.y = "name")
# Print head of the data
head(m2)

الإخراج:

##surname     nationality		title
## 1 Hitchcock          UK		Psycho
## 2 Hitchcock          UK		North by Northwest
## 3 Polanski          Poland		Chinatown
## 4 Scorsese           US		Taxi Driver
## 5 Spielberg          US		Super 8
## 6 Spielberg          US		Catch Me If You Can
# Check if data are identical
identical(m1, m2)

الإخراج:

## [1] TRUE

يوضح هذا أن عملية الدمج يتم تنفيذها حتى لو كانت أسماء الأعمدة مختلفة.

مباراة جزئية

أدى الربط الداخلي المذكور أعلاه إلى حذف أي بيانات لا يوجد لها نظير. ليس من المستغرب ألا تحتوي مجموعتا البيانات على نفس متغيرات المفتاح المشترك. مطابقة كاملة، يعود إطار البيانات فقط الصفوف الموجودة في إطار البيانات x و y. مع دمج جزئي، فمن الممكن الاحتفاظ بالصفوف التي لا تحتوي على صفوف متطابقة في إطار البيانات الآخر. ستحتوي هذه الصفوف على NA في تلك الأعمدة التي عادةً ما تكون مملوءة بقيم من y. يمكننا القيام بذلك عن طريق تعيين all.x= TRUE.

على سبيل المثال، يمكننا إضافة منتج جديد، لوكاس، إلى إطار بيانات المنتجين دون الحاجة إلى مراجع الأفلام الموجودة في إطار بيانات الأفلام. إذا قمنا بتعيين all.x= FALSE، فسيقوم R بدمج القيم المتطابقة فقط في مجموعتي البيانات. في حالتنا، لن يتم دمج المنتج لوكاس في النتيجة، لأنه غير موجود في إحدى مجموعتي البيانات.

دعونا نرى أبعاد كل مخرج عندما نحدد all.x= TRUE ومتى لا نفعل ذلك.

# Create a new producer
add_producer <-  c('Lucas', 'US')
#  Append it to the ` producer` dataframe
producers <- rbind(producers, add_producer)
# Use a partial merge 
m3 <-merge(producers, movies, by.x = "surname", by.y = "name", all.x = TRUE)
m3

الإخراج:

يُظهر خرج وحدة التحكم أدناه صف لوكاس الإضافي، مع استبدال NA بعنوان الفيلم المفقود.

مخرجات وحدة التحكم لعملية الدمج الجزئي تُظهر لوكاس مع قيمة NA في عمود العنوان

# Compare the dimension of each data frame
dim(m1)

الإخراج:

## [1] 7 3
dim(m2)

الإخراج:

## [1] 7 3
dim(m3)

الإخراج:

## [1] 8 3

كما نرى، فإن إطار البيانات الجديد هو 8×3، مقارنةً بـ 7×3 لـ m1 و m2. يقوم برنامج R بملء عمود العنوان بـ NA لـ Lucas، المنتج الذي لا يوجد له صف مطابق في إطار بيانات الأفلام.

دمج الدوال مقابل دمج الدوال باستخدام dplyr في لغة R

تقوم لغة R الأساسية بحل كل عملية ربط باستخدام دالة واحدة ومجموعة من العلامات. com.dplyr بدلاً من ذلك، تمنح الحزمة كل عملية ربط فعلها الخاص، وهو ما تجده العديد من الفرق أسهل في القراءة في خط الأنابيب.

المعايير دمج القاعدة() ينضم dplyr
اختيار نقطة الالتقاء جميع العلامات x / جميع العلامات y / جميع العلامات تم تسميتها في الفعل: left_join()، full_join()
ترتيب الصفوف يتم الترتيب حسب المفتاح إلا إذا كانت قيمة sort تساوي FALSE يتم الحفاظ على ترتيب الطاولة اليسرى
سرعة الإطارات الكبيرة أبطأ عموما أسرع
عمود المفتاح مفقود يفشل في وقت متأخر أو يدمج البيانات في الأعمدة الخاطئة الأخطاء فوراً
تبعيات قاعدة R، لا حاجة للتثبيت يتطلب حزمة dplyr

يترجم دمج الكلمتين الموضحتين أعلاه مباشرة إلى أفعال dplyr:

library(dplyr)
# Same inner join as merge(producers, movies, by.x = "surname", by.y = "name")
m4 <- inner_join(producers, movies, by = c("surname" = "name"))
# Same partial merge as all.x = TRUE
m5 <- left_join(producers, movies, by = c("surname" = "name"))

يُعدّ دمج الملفات الأساسية (Base merge()) الخيار الأكثر أمانًا داخل حزمة لا ينبغي أن تحتوي على أي تبعيات. أما dplyr فهو الخيار الأفضل في التحليل التفاعلي، حيث تُعدّ سهولة القراءة والسرعة أكثر أهمية.

أخطاء الدمج الشائعة في لغة R وكيفية إصلاحها

معظم مشاكل الدمج تظهر على شكل عدد صفوف غير متوقع بدلاً من رسالة خطأ، لذا فإن التحقق من dim() بعد كل عملية دمج هو عادة تستحق البناء.

  • تحتوي النتيجة على صفوف أكثر من أي من المدخلات. يؤدي تكرار المفتاح في كلا الإطارين إلى إنشاء عملية ربط متعددة الأطراف، ويعيد R جميع التوليفات الممكنة. افحص المفاتيح باستخدام الأمر table(duplicated(x$k)) قبل الدمج.
  • النتيجة فارغة. تختلف أعمدة المفاتيح عادةً في نوعها، أو قد يحتوي أحدها على مسافات زائدة. قم بتشغيل الدالة str() على كلا الإطارين، ثم نظّف المفتاح باستخدام الدالة trimws() قبل الدمج.
  • تعود الأعمدة على شكل title.x و title.y. يحتوي كلا الإطارين على عمود غير رئيسي يحمل نفس الاسم. مرر اللواحق = c(“_producer”, “_film”) لجعل المصدر واضحًا.
  • لم تعد الصفوف مرتبة بترتيبها الأصلي. تقوم الدالة merge() بالفرز بناءً على المفتاح افتراضيًا. أضف sort = FALSE، أو استخدم فرز صريح بعد ذلك.
  • فشل أحد المقارنات الرئيسية في بعض العوامل. قارن الأحرف، وليس مستويات العوامل: قم بتغليف المفتاح في as.character() قبل دمج الإطارات التي تم إنشاؤها في ظل الإعدادات الافتراضية القديمة لـ R.

عندما يتعين تشغيل عملية الدمج نفسها بشكل متكرر، قم بتضمينها في وظيفة محددة من قبل المستخدم لذا لا يمكن أن تتغير الوسائط بين عمليات التشغيل.

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

يدمج R البيانات بناءً على كل اسم عمود مشترك بين الإطارين. في حالة وجود عمود مشترك واحد، يكون ذلك مناسبًا؛ أما في حالة وجود عدة أعمدة مشتركة، فإنه يُضيّق نطاق النتائج تلقائيًا، وفي حالة عدم وجود أي عمود مشترك، فإنه يُجري عملية دمج متقاطع. إن تسمية المفتاح بشكل صريح تُجنّبنا جميع هذه المفاجآت.

ليس في استدعاء دالة الدمج (merge()) واحد. قم بتسلسل الاستدعاءات، أو قم بطي القائمة باستخدام Reduce(function(x, y) merge(x, y, by = “k”), list(df1, df2, df3)). تحقق من عدد الصفوف بعد كل خطوة، لأن المفاتيح المكررة تتراكم بسرعة.

يحتوي كلا الإطارين على عمود غير أساسي يحمل نفس الاسم، لذا يقوم R بتمييزهما. مرر suffixes = c(“_producer”, “_film”) لإعطاء النسخ أسماءً ذات معنى، أو احذف العمود الزائد قبل الدمج.

لا، تقوم الدالة merge() بفرز النتائج بناءً على عمود المفتاح افتراضيًا. مرر sort = FALSE للحفاظ على ترتيب النتائج الواردة، أو استخدم com.dplyr join، الذي يحافظ على ترتيب الإطار الأيسر.

قم بتوفير متجه: merge(x, y, by = c(“surname”, “year”)). عندما تختلف الأسماء، مرر المتجهات المطابقة إلى by.x و by.y. يجب أن يسرد كلا المتجهين الأعمدة بنفس الترتيب.

استخدم by = “row.names”، أو الاختصار by = 0. يضيف R أسماء الصفوف مرة أخرى كعمود يسمى Row.names، والذي عادةً ما ترغب في إعادة تسميته أو حذفه قبل متابعة التحليل.

صف الإطارين وعدد الصفوف، وسيشير مساعد الذكاء الاصطناعي إلى المفاتيح المكررة كسبب محتمل، ويقترح فحصًا باستخدام دالة duplicated(). تأكد من التشخيص بمقارنته ببياناتك قبل تغيير عملية الربط.

نعم. RStudio يأتي إصدار سطح المكتب 2023.09.0 والإصدارات الأحدث مزودًا بخيار الاشتراك مساعد الطيار جيثب عملية دمج تقوم بإنشاء عملية دمج من تعليق. تحقق من نوع الربط الذي تختاره، لأن علامة خاطئة تُغير عدد الصفوف دون أن يلاحظ المستخدم ذلك.

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