برمجة إحصائيةتحليل البيانات النفسية

كيفية إصلاح: خطأ في xy.coords(x, y, xlabel, ylabel, log) : أطوال ‘x’ و ‘y’ مختلفة

دليل إرشادي متقدم وشامل لتشخيص وتصحيح الخطأ الإحصائي والبرمجي الشهير xy.coords(x, y) في لغة R أثناء تحليل البيانات وبناء المخططات البيانية.

تاريخ النشر

تُعد لغة البرمجة الإحصائية R Project for Statistical Computing إحدى الركائز الأساسية التي يعتمد عليها الباحثون وعلماء البيانات في إجراء التحليلات المتقدمة وبناء النماذج وتوليد التمثيلات الرسومية المعقدة. ومع ذلك، يواجه المشتغلون بهذه البيئة، لا سيما في مجالات القياس النفسي والعلوم السلوكية، حزمة من الأخطاء البرمجية التي قد تبدو محيرة في ظاهرها ولكنها تحمل دلالات بنيوية عميقة تتعلق بطبيعة التعامل مع هياكل البيانات والذاكرة. ومن بين أكثر هذه الأخطاء شيوعاً واستدعاءً للتوقف هو الخطأ الشهير: error in xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ، والذي يشير بوضوح لا يقبل اللبس إلى انهيار التكافؤ الرياضي والبعدي بين المتغيرين المراد تمثيلهما على المحاور الديكارتية.

إن فهم كوامن هذا الخطأ يتجاوز مجرد البحث عن حل سريع لترقيع الشيفرة البرمجية؛ إذ يتطلب سبر أغوار البنية الداخلية لمحرك الرسم التأسيسي في بيئة R (Base Graphics Engine) ومعرفة الكيفية التي تعالج بها دالة xy.coords الإحداثيات الثنائية قبل تحويلها إلى بكسلات ونقاط بصرية على الشاشة. ينشأ هذا التباين البعدي نتيجة عوامل متعددة، تتراوح بين المعالجة غير المتناظرة للقيم المفقودة، وعمليات التصفية والترشيح المستقلة للمتغيرات، والأخطاء الناتجة عن استيراد الجداول ودمج المصفوفات من مصادر غير متجانسة كملفات الاستبيانات السيكومترية أو السلاسل الزمنية غير المتزامنة.

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

1. مقدمة بنيوية حول دالة xy.coords ودورها في بيئة لغة R

1.1 التعريف التقني بدالة xy.coords الداخلية وموقعها في البنية الرسومية

تمثل دالة xy.coords إحدى الأدوات الأساسية غير المرئية بصورة مباشرة للمستخدم العادي في حزمة grDevices المدمجة في صلب نظام R، حيث تعمل كواجهة برمجية موحدة (Canonical Parsing Interface) تتولى استقبال المدخلات الهيكلية المتنوعة وترجمتها إلى بنية قياسية تتألف من إحداثيات ثنائية صريحة. وظيفة هذه الدالة تتجاوز مجرد التحقق؛ فهي المحول الهندسي الذي يضمن أن أي مدخل، سواء كان متجهاً رقمياً، أو مصفوفة ذات عمودين، أو قائمة مقترنة، أو حتى صيغة رياضية من نمط (Formula Interface: y ~ x)، يتم تفكيكه واستخلاص المتجه السيني (x) والمتجه الصادي (y) منه بأعلى درجات الدقة الحسابية.

تعتمد كافة دوال الرسم التأسيسية مثل plot()، وlines()، وpoints()، وsegments()، وsmoothScatter() على هذه الدالة كخطوة أولى وحتمية قبل الشروع في أي عملية تخصيص للذاكرة الرسومية أو حجز للنطاقات البيانية (Plotting Limits). عندما يقوم الباحث بتمرير كائنين للدالة، تقوم xy.coords باستخراج التسميات الافتراضية للمحاور (X-label و Y-label) عبر قراءة أسماء المتغيرات (De-parsing Expressions)، ثم تتحقق مما إذا كان هناك تحويل لوغاريتمي مطلوب للمحاور، وتختبر التوافق الهندسي والنوعي بين الأرقام لإنتاج قائمة نهائية متجانسة تحتوي على العناصر $x، $y، $xlab، $ylab، و$log.

تعتبر هذه الآلية صمام الأمان المعماري للنظام الرسومي؛ فبدونها ستضطر كل دالة رسم مستقلة إلى إعادة كتابة خوارزميات فك تشفير وتدقيق متجهات الإحداثيات، مما يرفع احتمالية الأخطاء غير المتوقعة (Bugs) في معالجة الذاكرة الرسومية المنخفضة المستوى (Low-level Graphics Engine). ومن ثم، فإن أي رسالة خطأ تصدر عن xy.coords تعكس فشلاً في مرحلة التجهيز والتحقق الأولية وقبل كتابة أي بكسل على جهاز العرض المخصص.

1.2 طبيعة العلاقة الاقترانية بين الإحداثيات الثنائية في الفضاء الإحصائي

يرتكز التمثيل البياني الإحصائي في الفضاء الإقليدي ثنائي الأبعاد على مفهوم التقابل الأحادي (One-to-One Mapping) الصارم بين أزواج البيانات؛ حيث تفترض النماذج الارتباطية والانحدارية ومخططات التشتت أن كل نقطة بيانية تمثل كياناً رصدياً واحداً يحمل قياسين متزامنين: قيمة على المحور الأفقي ($x_i$) وقيمة مقابلة على المحور الرأسي ($y_i$). هذا التناظر الهندسي يفرض تكافؤاً بعدياً تاماً (Dimensional Equivalence)، بحيث يجب أن ينتمي المتجهان إلى فضاء ذي أبعاد متطابقة رياضياً، أي أن طول المتجه الأول يجب أن يتطابق مطلقاً مع طول المتجه الثاني ($N_x = N_y$).

عندما ينهار هذا التناظر البعدي، يتعطل المنطق الرياضي للخوارزميات الحسابية المسؤولة عن تحويل الإحداثيات المكانية إلى أبعاد نسبية على الشاشة. لا يمكن لخوارزميات التصيير البصري (Rendering Engine) تخمين النقطة التي يجب أن تقترن مع مشاهدة فائضة في أحد المتغيرين، كما لا يمكنها افتراض قيم وهمية لملء الفراغات دون توجيه صريح من المحلل الإحصائي؛ لأن أي سلوك افتراضي تلقائي قد يؤدي إلى تشويه المعالم الإحصائية للعلاقة وتوليد ارتباطات زائفة أو تباينات مضللة في البيانات.

في البيئات الحسابية الحديثة، يُعد الحفاظ على التكامل الإحداثي شرطاً أساسياً لضمان دقة الرسوم التكرارية وخطوط الاتجاه العام وتقديرات الكثافة الاحتمالية. إن غياب التماثل الإحداثي يمنع حساب مقاييس التغاير المشترك (Covariance) ومصفوفات الارتباط (Correlation Matrices) التي تُبنى عليها الرسوم البيانية، مما يجعل التوقف الحتمي للنظام ورمي استثناء برمجي هو الخيار المنطقي الوحيد لحماية نزاهة التحليل الإحصائي من التفسيرات المشوهة.

2. التشريح الدقيق لجذر الخطأ: لماذا تنشأ رسالة ‘x’ and ‘y’ lengths differ؟

2.1 آلية التحقق من التساوي في كود المصدر لدالة xy.coords

لفهم الكيفية التي ينفجر بها هذا الخطأ برمجياً، يجب النظر في الشيفرة المصدرية (Source Code) للغة R داخل تعريف الدالة xy.coords. بعد أن تستخلص الدالة المتجهين $x$ و $y$ من المدخلات المختلفة وتقوم بإزالة أو استخراج الأبعاد عبر دوال القياس الداخلية، تصل الشيفرة إلى اختبار منطقي صارم وغير قابل للتفاوض، حيث يتم التحقق من الشرط الآتي:

يتم تقييم التعبير المنطقي length(x) != length(y)؛ وإذا كانت النتيجة المنطقية صحيحة (TRUE)، يقوم محرك R باستدعاء دالة المقاطعة stop("'x' and 'y' lengths differ")، مما يؤدي إلى قطع تدفق التنفيذ الفوري وإلغاء استدعاء مكدس العمليات (Call Stack) للرسم. ترفض الدالة المضي قدماً لأنها مصممة لتجهيز إحداثيات رسومية، واللاتماثل يعني استحالة بناء مصفوفة الإحداثيات الثنائية الموحدة.

هناك تمايز دقيق يجب إدراكه بين الحالات المختلفة للأطوال الشاذة:

  • المتجهات غير المتساوية (Unequal Vectors): كأن يحتوي $x$ على 100 عنصر بينما يحتوي $y$ على 95 عنصراً، وهو السبب النمطي الشائع لظهور الخطأ.
  • المتجهات ذات الطول الصفري (Zero-length Vectors): مثل تمرير كائن تم تفريغه بالكامل نتيجة تصفية خاطئة (مثل numeric(0)) ومقارنته بمتجه يحمل قياسات فعلية.
  • المتجهات الفارغة أو غير المعرفة (NULL/Uninitialized): حيث يؤدي تمرير قيمة NULL لأحد الوسائط دون الآخر إلى اعتبار طوله صفراً، مما يشعل نفس شرط التوقف البعدي.

2.2 الخلل الهيكلي بين المتغير المستقل والمتغير التابع

في التطبيقات الإحصائية والمسحية الواقعية، نادراً ما يكون سبب عدم التطابق خطأً مطبعياً بسيطاً في كتابة الكود؛ بل غالباً ما يعود إلى خلل هيكلي في معالجة مصفوفات الملاحظات والبيانات الخام. فعلى سبيل المثال، في الدراسات المسحية والتجريبية التي تعتمد على تصميم العينات المستقلة أو الاستجابات المتعددة، قد يحدث عدم توافق ناتج عن دمج متغيرات تم جمعها من عينات غير متكافئة الحجم دون ربطها بمعرف فريد (Primary Key).

يتجلى هذا الخلل بوضوح في التصاميم التتبعية والطولية (Longitudinal Designs)، حيث يتم قياس استجابات الأفراد في القياس القبلي (Pre-test) ومقارنتها بالقياس البعدي (Post-test). إذا تعرضت الدراسة لتسرب في العينة (Sample Attrition) في مرحلة القياس البعدي، فإن متجه القياس القبلي سيحتفظ بحجمه الأصلي (مثلاً $N=150$) بينما يتقلص متجه القياس البعدي نتيجة انسحاب بعض المشاركين إلى ($N=128$). إذا حاول الباحث رسم هذين المتغيرين كمتجهين سائبين دون مواءمة سابقة لصفوف المشاركين، فإن النظام سيفشل مباشرة معلناً تباين الأطوال.

كذلك تظهر الأزمة بوضوح عند التعامل مع السلاسل الزمنية والبيانات الفسيولوجية (مثل معدل ضربات القلب أو إشارات التخطيط الدماغي EEG) المأخوذة بترددات أخذ عينات (Sampling Frequencies) مختلفة. إذا كانت السلسلة الأولى تسجل كل ثانية بينما تسجل السلسلة الثانية كل دقيقة، فإن تجميع المتغيرين دون إعادة تشكيل الترددات (Resampling/Interpolation) سيؤدي حتماً إلى تفاوت ضخم في أطوال المتجهات وانهيار التمثيل الإحداثي المشترك.

3. إعادة إنتاج الخطأ مخبرياً: نماذج تطبيقية وحالات معزولة

3.1 النموذج القياسي الأساسي لحدوث الخطأ في التمثيل النقطي (Scatterplot)

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

المتغير المستقل $x$ يمثل ساعات الدراسة ويحتوي على أربعة عناصر: x <- c(2, 5, 5, 8)، بينما يمثل المتغير التابع $y$ درجات الطلاب في الاختبار النهائي ويحتوي على ستة عناصر: y <- c(22, 28, 32, 35, 40, 41). عند محاولة استدعاء دالة الرسم الأساسية عبر الأمر plot(x, y)، يقوم المحرك الداخلي فوراً بتمرير هذين الوسيطين إلى xy.coords.

في هذه اللحظة، تحسب الدالة طول المتجه الأول فترصده مساوياً لـ 4 (length(x) = 4)، ثم تحسب طول المتجه الثاني فترصده مساوياً لـ 6 (length(y) = 6). بما أن الشرط المنطقي $4 \neq 6$ محقق، يطلق المحرك الإحصائي استثناء التوقف الفوري المتبوع بالنص:

Error in xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ

تحليل المخرجات البرمجية يظهر أن العملية لم تصل أبداً إلى مرحلة فتح النافذة الرسومية (Graphics Device) أو تهيئة المحاور؛ بل أُجهضت في الميكروثانية الأولى من فحص المدخلات، مما يؤكد أن الدالة تمارس دور الحاجز الوقائي لمنع تخصيص موارد الحوسبة لمهام غير معرفة هندسياً.

3.2 إعادة إنتاج الخطأ عند التعامل مع الجداول والبيانات متعددة الأبعاد

لا يقتصر حدوث الخطأ على المتجهات الرقمية البسيطة، بل يمتد إلى هياكل البيانات الأكثر تعقيداً مثل الأطر البيانية (Data Frames)، والقوائم غير المتجانسة (Lists)، ومخرجات نماذج التحليل الإحصائي المتقدمة. يقع الباحثون في هذا المأزق غالباً عند استخراج أعمدة من أطر بيانية مختلفة الأحجام ومحاولة تمثيلها دون ربط منهجي.

لنفترض وجود إطار بيانات أول يحتوي على بيانات ديموغرافية لـ 50 مفحوصاً، وإطار بيانات ثانٍ يحتوي على استجابات المسح النفسي لـ 45 مفحوصاً بعد استبعاد الحالات الشاذة. إن محاولة تنفيذ أمر مثل plot(df1$Age, df2$AnxietyScore) ستصطدم مباشرة باختلاف طول العمودين، حيث يبلغ طول الأول 50 والآخر 45، وهو ما يستدعي نفس رسالة الخطأ فوراً.

يتكرر السيناريو ذاته عند العمل مع القوائم غير المتماثلة؛ فإذا احتوت قائمة ما على عناصر فرعية تمثل مجموعات تجريبية ذات أحجام عينات مختلفة (Unequal Group Sizes)، وحاول الباحث رسم عنصرين منها مباشرة: plot(my_list[[1]], my_list[[2]])، سيفشل الرسم تماماً ما لم تكن أحجام المجموعات متطابقة بمحض الصدفة. كذلك يظهر الخطأ عند رسم مخرجات الانحدار الخطي (Linear Regression)، كأن يحاول المحلل رسم القيم المتوقعة (Fitted Values) مقابل متجه بيانات خارجي تم تعديله أو حذفت منه بعض الملاحظات، مما يولد تضارباً بين أبعاد متجه التنبؤات وأبعاد المتغير الفعلي.

4. البروتوكول التشخيصي: أدوات برمجية للتحقق من أبعاد المتجهات

4.1 استخدام الدوال البنائية لمعاينة الأطوال والأبعاد

عند مواجهة رسالة الخطأ 'x' and 'y' lengths differ، يجب أن يبدأ بروتوكول التدخل التشخيصي المنهجي بفحص الكينونة البعدية لكافة المتغيرات المشاركة في عملية الرسم، بدلاً من التخمين العشوائي. توفر بيئة R مجموعة من الدوال البنائية السريعة التي تتيح الكشف الفوري عن مواضع الخلل:

  • دالة القياس الطولي المباشر: استخدام length(x) و length(y) لمعاينة عدد العناصر في كل متجه بصورة مستقلة ومقارنة القيمتين حسابياً.
  • الفحص المنطقي التلقائي: كتابة اختبار شرطي صريح في الطرفية مثل length(x) == length(y) لمعرفة ما إذا كانت النتيجة تعيد FALSE والتأكد من وجود التباين.
  • فحص الهيكل الداخلي الشامل: تطبيق دالة str(x) و str(y)، والتي لا تقتصر على عرض الطول فحسب، بل تكشف عن طبيعة الكائن، ونوعه (Numeric, Factor, Character)، وأولى القيم المخزنة داخله، مما يكشف ما إذا كان أحد الكائنات مصفوفة أو قائمة بدلاً من كونه متجهاً بسيطاً.
  • فحص أبعاد المصفوفات والأطر: استخدام دالة dim() ودالة NROW()؛ حيث تُعد NROW() بالغة الأهمية لأنها تعامل المتجهات الأحادية والمصفوفات والأطر البيانية بأسلوب قياسي موحد وتُرجع عدد الصفوف أو العناصر بدقة.

يتيح هذا الفحص الأولي معرفة الفارق العددي الدقيق بين المتغيرين، وهو ما يمهد للخطوة التالية في تحديد سبب تسرب أو زيادة هذه الملاحظات في أحد الطرفين دون الآخر.

4.2 التفتيش البصري والجدولي للبيانات الخام

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

يتيح استدعاء head(x, 10) و head(y, 10) مقارنة البدايات الزمنية والترتيبية للمتغيرين، بينما يتيح استدعاء tail(x, 10) و tail(y, 10) كشف ما إذا كانت هناك ذيول مفقودة أو سجلات مقطوعة في نهاية أحد المتجهات نتيجة مشاكل في إيقاف التسجيل أو القراءة الجزئية للملفات.

كذلك يوفر استخدام دالة summary() نظرة بانورامية حول التوزيعات التكرارية وعدد القيم المفقودة (NA’s) في كلا المتغيرين، مما يشير فوراً إلى ما إذا كان أحد المتجهات قد تعرض لحذف داخلي غير متزامن. ولإجراء فحص أكثر دقة وتفاعلية، يُنصح بتوظيف حزمة tibble أو دالة View() التفاعلية في بيئة RStudio، حيث يمكن عرض البيانات كجدول متكامل يسهل تتبع الفهارس (Row Indices) فيه واكتشاف الصفوف الفارغة أو المتغيرة المحاذاة خطوة بخطوة.

5. مسببات عدم تطابق الأطوال في معالجة البيانات السيكومترية والنفسية

5.1 تأثير تسرب العينة والاستجابات غير المكتملة في الاستبيانات

في ميدان القياس النفسي والبحوث السلوكية، تشكل طبيعة البيانات المجمعة من البشر مصدراً رئيسياً للتحديات الهيكلية. من أبرز هذه التحديات ظاهرة الفقدان العشوائي للبيانات (Missing at Random – MAR) الناتجة عن امتناع بعض المستجيبين عن الإجابة على فقرات محددة في مقاييس الشخصية والاتجاهات، أو إغلاق الاستبيان الإلكتروني قبل إتمامه.

عندما يتعامل الباحث مع هذه البيانات عبر استخراج كل متغير كمتجه مستقل، فإن أي استبعاد لحالات معينة من متغير واحد دون تطبيق نفس المعيار على المتغير الآخر يؤدي فوراً إلى تباين الأطوال. يظهر هذا الخلل بشكل حاد في التصاميم التجريبية التي تتضمن مقارنة بين عينة تجريبية وعينة ضابطة ذات أحجام غير متساوية ($n_1 \neq n_2$)؛ حيث يحاول بعض الباحثين المبتدئين رسم درجات العينة الأولى في المحور السيني مقابل درجات العينة الثانية في المحور الصادي مباشرة دون إدراك أن دالة plot(x, y) تتطلب أزواجاً متناظرة لنفس الأفراد وليست مصممة للمقارنة بين مجموعتين مستقلتين دون هيكلة وسيطة.

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

5.2 الأخطاء الناجمة عن المعالجة القبلية للمتغيرات النفسية

تمثل المعالجة القبلية للبيانات (Data Preprocessing) المرحلة الأكثر حساسية وتوليداً للأخطاء البعدية غير المقصودة. ومن أكثر الممارسات الخاطئة شيوعاً قيام المحلل بحذف القيم الشاذة المتطرفة (Outliers) من متغير الاكتئاب، مثلاً عبر تطبيق معيار الانحراف المعياري ($Z > 3$)، وحفظ النتيجة في متجه جديد depression_clean، ثم محاولة رسم هذا المتجه المنقى في مواجهة متغير القلق الأصلي anxiety_raw الذي لم تُحذف منه تلك الحالات.

هذا الإجراء يؤدي تلقائياً إلى أن يصبح طول depression_clean أقل من طول anxiety_raw بمقدار عدد الحالات الشاذة المستبعدة، مما يضمن ظهور خطأ 'x' and 'y' lengths differ فور استدعاء دالة الرسم. ينطبق الأمر نفسه على شروط التصفية السيكومترية غير المتوازية، مثل تصفية درجات مقياس فرعي بناءً على سرعة الاستجابة الزمنية لبعض الفقرات دون تطبيق نفس المرشح على المقياس الكلي.

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

6. الحلول المباشرة: مواءمة وتوحيد أطوال المتجهات برمجياً

6.1 تقليص المتجه الأطول عبر الفهرسة والتجزيء (Indexing & Slicing)

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

إذا كان المتجه $y$ أطول من $x$، يمكن تمرير التعبير y_subset <- y[1:length(x)]، مما يجبر $y$ على اتخاذ نفس أبعاد $x$ تماماً ويسمح لدالة plot(x, y_subset) بالعمل دون أخطاء. ومع ذلك، يجب توخي الحذر الشديد من الناحية الإحصائية عند اللجوء إلى هذا الحل؛ إذ إن حذف العناصر الأخيرة عشوائياً يفترض ضمناً أن البيانات مرتبة بطريقة لا تؤثر على التوزيع، وهو افتراض قد يكون كارثياً إذا كانت البيانات مرتبة زمنياً أو تصاعدياً.

بدلاً من الاقتطاع البسيط من النهاية، يمكن استخدام تقنيات أخذ العينات العشوائية المتساوية (Subsampling) دون إرجاع عبر دالة sample()، مثل y_sampled <- sample(y, length(x))، إذا كان الهدف هو مقارنة التوزيعات العامة دون افتراض الاقتران الفردي. لكن في دراسات الارتباط والانحدار، يظل التقليص القسري دون مطابقة المعرفات (IDs) سلوكاً خاطئاً منهجياً يجب تجنبه لصالح المواءمة الهيكلية القائمة على مطابقة الحالات.

6.2 تمديد المتجه الأقصر عبر التكرار والتوليد الإحصائي

في المقابل، تتطلب بعض التصاميم التجريبية ذات القياسات المتكررة (Repeated Measures) أو التصاميم العاملية تمديد المتجه الأقصر ليتطابق مع حجم القياسات المتعددة. على سبيل المثال، إذا كان لدينا متغير يمثل الظروف التجريبية الثلاثة (Control, Treatment A, Treatment B) ونريد تمثيله في مواجهة استجابات 90 مشاركاً موزعين بالتساوي على هذه الظروف، فإن المتجه الأصلي ذو العناصر الثلاثة يجب تكراره ليصبح بطول 90.

تُستخدم دالة التكرار rep() ببراعة لتحقيق هذا الغرض، حيث يمكن التحكم في نمط التكرار سواء عبر تكرار كل عنصر على حدة (rep(conditions, each = 30)) أو تكرار المتجه ككل بصورة دورية (rep(conditions, times = 30))، مما ينتج متجهاً جديداً متطابق الأبعاد تماماً مع متغير الاستجابات ويزيل العائق البعدي أمام دوال الرسم.

من الضروري هنا التنبيه إلى محاذير ما يُعرف في لغة R بـ “إعادة التدوير التلقائي للمتجهات” (Vector Recycling Mechanism). فبينما تقبل بعض العمليات الحسابية تدوير المتجهات القصيرة تلقائياً لتلائم المتجهات الطويلة، فإن دوال الرسم المنبثقة عن xy.coords ترفض هذا التدوير التلقائي عمداً، وذلك لحماية المحلل من الخلط الكارثي بين البيانات المقترنة فعلياً وتلك المولدة بصورة آلية غير مقصودة.

7. إدارة القيم المفقودة (NA Values): المعالجة الجذرية المنهجية

7.1 تأثير دوال إزالة المفقودات التلقائية على تفكك الأبعاد

يعد التعامل غير الواعي مع القيم المفقودة (Missing Values المرموز لها بـ NA في R) السبب الأكثر شيوعاً لتوليد خطأ 'x' and 'y' lengths differ لدى المحللين والباحثين. يكمن الفخ البرمجي النمطي في قيام الباحث بتطبيق دوال الحذف التلقائي مثل na.omit() على كل متغير بصورة منفردة ومستقلة:

عندما ينفذ الباحث الأمرين التاليين: x_clean <- na.omit(x) متبوعاً بـ y_clean <- na.omit(y)، فإن ما يحدث فعلياً هو حذف القيم المفقودة الخاصة بـ $x$ فقط من المتجه الأول، وحذف القيم المفقودة الخاصة بـ $y$ فقط من المتجه الثاني. إذا كان المتجه $x$ يحتوي على 3 قيم مفقودة بينما يحتوي $y$ على 7 قيم مفقودة في مواقع مختلفة، فإن النتيجة الحتمية ستكون أن length(x_clean) لن يساوي مطلقاً length(y_clean)، مما يؤدي إلى فشل فوري عند محاولة استدعاء plot(x_clean, y_clean).

للكشف عن هذا التفكك وتتبع مواقع القيم المفقودة بدقة، يجب استخدام الدوال المنطقية الاستكشافية مثل is.na(x) لتحديد المواقع المنطقية، ودالة which(is.na(x)) لاستخراج الفهارس العددية الدقيقة للحالات المعطوبة، مما يمهد لتطبيق استراتيجية الحذف المتزامن المتبادل بدلاً من الحذف المنفرد المعزول.

7.2 تطبيق دالة complete.cases لحماية التناظر الإحداثي

تتمثل الممارسة الإحصائية والبرمجية الفضلى لحل معضلة القيم المفقودة في تجميع المتغيرين أولاً داخل إطار بيانات موحد (Data Frame) قبل الشروع في أي عملية حذف، ثم تطبيق دالة الحالات المكتملة complete.cases() لضمان إسقاط السجل بأكمله إذا فُقدت قيمته في أي من المتغيرين المقترنين:

يتم هذا الإجراء المنهجي عبر الخطوات البرمجية التالية:

  • تجميع البيانات في كائن موحد: إنشاء إطار بيانات مشترك عبر الأمر df <- data.frame(x = x, y = y)، وهو ما يضمن ربط كل قيمة $x_i$ بالقيمة $y_i$ في نفس الصف.
  • تطبيق مصفوفة الترشيح المنطقي: استخدام دالة complete.cases(df) التي تُرجع متجهاً منطقياً يحمل القيمة TRUE فقط للصفوف التي تخلو من أي NA في كلا العمودين.
  • استخراج الحالات النظيفة متزامناً: تصفية الجدول بالصيغة القياسية df_clean <- df[complete.cases(df), ]، مما يضمن تطابق أطوال الأعمدة تماماً بعد التصفية.
  • الرسم الآمن: استدعاء دالة الرسم باستخدام الأعمدة المنقاة plot(df_clean$x, df_clean$y) بكل موثوقية.

كذلك يمكن استخدام دالة na.exclude() عند التعامل مع نماذج الانحدار، حيث تتميز بقدرتها على الاحتفاظ بمعلومات التراكيب الأصلية وتسهيل استعادة أبعاد المتجهات والتنبؤات المتوافقة دون الإخلال بهيكل البيانات الكلي.

8. معالجة أخطاء الاستيراد وهيكلة البيانات من الملفات الخارجية

8.1 مشكلات قراءة ملفات CSV وExcel وتفاوت نهايات الأعمدة

تشكل ملفات البيانات الخارجية، مثل جداول CSV و Excel، بيئة خصبة للأخطاء البعدية غير المرئية. من أبرز هذه المشكلات وجود مسافات بيضاء أو أسطر فارغة وهمية في نهاية أحد الأعمدة دون بقية الأعمدة؛ فعندما يقوم برنامج الجداول الإلكترونية بتصدير الملف، قد يُدرج صفوفاً تحتوي على قيم نصية فارغة (Empty Strings: "") مما يدفع محرك R إلى قراءة ذلك العمود كمتجه أطول يحتوي على عناصر إضافية غير مرئية للعين المجردة.

لتفادي هذا التفاوت أثناء استيراد البيانات عبر دالة read.csv() أو read.table()، يجب ضبط الوسائط الإجرائية بعناية فائقة لمنع تضخيم أطوال الأعمدة:

  • تفعيل خيار تجاهل الأسطر الفارغة: blank.lines.skip = TRUE لتخطي أي صفوف خالية تماماً من البيانات.
  • تعطيل التعبئة التلقائية غير المنضبطة: fill = FALSE لإجبار الدالة على التوقف وإطلاق تنبيه إذا كانت الصفوف غير متساوية الطول بدلاً من ملئها تلقائياً وتوليد تباينات وهمية.
  • تحديد رموز القيم المفقودة بوضوح: na.strings = c("NA", "", " ", "NULL") لضمان تحويل كافة الخلايا الفارغة والنصوص الوهمية إلى قيم NA قياسية يسهل تنظيفها لاحقاً.

كما يجب الانتباه إلى الفواصل العشرية (Decimals vs Commas)؛ فإذا استوردت بيانات تحتوي على فاصلة كعلامة عشرية دون ضبط وسيط dec = ","، قد ينقسم العمود الرقمي الواحد إلى نص معطوب أو يتسبب في قراءة غير متجانسة تفصل القياسات وتفسد تناظر المتجهات.

8.2 دمج مجموعات البيانات (Merging & Joining) المتباينة

عند بناء المشاريع البحثية الكبيرة، غالباً ما يتم جمع المتغير المستقل (مثل السمات الديموغرافية والدرجات الأساسية) في ملف مستقل، بينما تُجمع المتغيرات التابعة (مثل مقاييس المتابعة) في ملف آخر. إن محاولة استخراج المتجه $x$ من الملف الأول والمتجه $y$ من الملف الثاني ورسمهما مباشرة دون عملية دمج علائقية (Relational Join) يقود حتماً إلى كارثة عدم تطابق الأطوال.

الحل الجذري يتطلب استخدام دالة الدمج التأسيسية merge() أو دوال حزمة dplyr الحديثة بالاعتماد على معرف مشترك فريد للمفحوصين (Subject ID). يوضح الإجراء التالي الكيفية السليمة لتأمين التناظر البعدي:

يتم تطبيق الربط الداخلي الحصري عبر merged_df <- inner_join(df_baseline, df_followup, by = "Subject_ID")، مما يضمن أن السجلات التي تظهر في الجدول النهائي هي فقط السجلات التي يمتلك أصحابها قياسات كاملة ومؤكدة في كلتا المرحلتين. هذا الإجراء يحمي التحليل من الوقوع في فخ الجداء الديكارتي (Cartesian Product) الناتج عن الدمج الخاطئ الذي يضاعف أطوال المتغيرات بشكل عشوائي ويفسد الهيكل الرياضي للإحداثيات الرسومية.

9. إجراءات التصفية والترشيح الآمنة للبيانات الإحصائية

9.1 الترشيح المتزامن للمتغيرات المرتبطة

أحد المبادئ البرمجية الأساسية في تحليل البيانات هو حظر إجراء التصفية المستقلة (Independent Filtering) على المتغيرات المقترنة تحليلياً. إذا تطلب التصميم الإحصائي استبعاد القيم السالبة أو غير المنطقية من المتغير المستقل $x$ (مثلاً: زمن الاستجابة الأصغر من الصفر)، فإن تطبيق التعبير x_filtered <- x[x > 0] يقتطع قياسات من $x$ ويترك $y$ بحجمه الأصلي، مما يؤدي فوراً إلى تدمير التقابل الأحادي بينهما.

لتنفيذ الترشيح الآمن للمتغيرات السائبة، يجب بناء ما يُعرف بـ “القناع المنطقي المشترك” (Shared Logical Mask) وتطبيقه بصورة متوازية ومتزامنة على كلا المتغيرين كما يلي:

يتم إنشاء شرط الفلترة الموحد: valid_cases <- (x > 0) & (!is.na(x)) & (!is.na(y)). بعد ذلك، يتم تطبيق هذا القناع المتجهي الموحد على كلا المتغيرين بالتساوي: x_clean <- x[valid_cases] و y_clean <- y[valid_cases]. يضمن هذا التطبيق المتوازي استبعاد نفس الحالات والفهارس من كلا الطرفين، مما يحفظ التساوي البعدي المطلق length(x_clean) == length(y_clean) ويجعل استدعاء plot(x_clean, y_clean) آمناً وخالياً تماماً من الأخطاء.

أما عند العمل داخل منظومة البيانات الحديثة، فإن استخدام dplyr::filter() يمثل الخيار الأمثل؛ حيث تعمل الدالة على مستوى الصف بأكمله داخل إطار البيانات، مما يحول تلقائياً دون حدوث أي انفصال بعدي بين الأعمدة المختلفة.

9.2 التعامل مع تصنيفات المجموعات الفرعية (Subgroup Analysis)

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

توفر بيئة R دوال متقدمة تضمن عزل المجموعات مع الحفاظ على الاتساق الداخلي لكل فئة:

  • دالة التقسيم الهيكلي: استخدام split(df, df$Gender) لتقسيم إطار البيانات إلى قوائم فرعية مغلقة ومستقلة، بحيث يحتفظ كل جدول فرعي داخل القائمة بالتناظر التام بين أعمدته.
  • التطبيق الفئوي الموحد: توظيف دالة tapply() أو by() لحساب المتوسطات والإحداثيات التلخيصية لكل فئة على حدة، مما ينتج متجهات متطابقة الأطوال تمثل ملخصات المجموعات بدقة.
  • التحقق الفئوي: استخدام table(df$Group) قبل الشروع في الرسم لمعاينة التوزيع العددي لكل فئة، والتأكد من عدم وجود مجموعات ذات حجم صفري أو تحتوي على مشاهدة يتيمة تكسر خوارزميات التصيير البياني.

10. مقارنة سلوك Base R مع بيئة ggplot2 الحديثة حيال الخطأ

10.1 فلسفة إطار البيانات الإلزامي في نظام Grammar of Graphics

يمثل الانتقال من حزمة الرسم الأساسية (Base Graphics) إلى الحزمة الحديثة ggplot2 تحولاً جوهرياً في فلسفة التعامل مع هياكل البيانات وأبعادها الرسومية. تتبنى ggplot2 فلسفة “قواعد بناء الرسوم البيانية” (Grammar of Graphics)، والتي تفرض شرطاً معمارياً حاسماً: يجب أن تكون كافة المتغيرات المراد تمثيلها مدمجة مسبقاً داخل كائن واحد من نوع إطار بيانات (Data Frame أو Tibble).

هذا القيد الإلزامي يقضي من المنبع على خطأ 'x' and 'y' lengths differ بصيغته التقليدية؛ لأن إطار البيانات في لغة R يمنع بنيوياً وجود أعمدة متباينة الأطوال داخل الكائن الواحد. ومع ذلك، إذا حاول المستخدم تمرير متجهات خارجية غير متساوية إلى دوال الجماليات (Aesthetics) داخل aes()، تطلق ggplot2 رسالة خطأ صريحة وموجهة تفيد بأن خصائص الإظهار يجب أن تطابق طول البيانات الأساسية:

Error: Aesthetics must be either length 1 or the same as the data

تتميز هذه الصياغة الحديثة بالوضوح الشديد؛ حيث تخبر المحلل فوراً بالخلل الدقيق وتمنعه من مزج متجهات سائبة مع بيانات الجدول، مما يعزز مناعة الشيفرة البرمجية ضد الانهيارات البعدية غير المتوقعة.

10.2 التحويل البرمجي بين البيئتين لحل الإشكاليات الرسومية

لمعالجة المشاكل الناتجة عن دوال Base R وتحقيق أقصى درجات الموثوقية الرسومية، يُنصح بإعادة كتابة تدفقات العمل التحليلي بصيغة ggplot2 الحديثة. يوضح الجدول المفاهيمي التالي مسار التحويل البرمجي الآمن:

بدلاً من كتابة الصيغة الهشة المعرضة لتباين الأطوال:

# Base R - معرض لانهيار الأطوال إذا تباينت المتجهات
plot(raw_vector_x, raw_vector_y)

يتم الانتقال إلى البناء الهيكلي المحصن داخل منظومة Tidyverse:

# Tidyverse / ggplot2 - بنية محصنة ضد تباين الأبعاد
library(ggplot2)
plot_data <- tibble(x = raw_vector_x, y = raw_vector_y) # يطلق خطأ فورياً هنا إذا تباينت الأطوال قبل الوصول للرسم
ggplot(plot_data, aes(x = x, y = y)) + geom_point()

توفر هذه المنهجية ميزة حاسمة إضافية؛ فعند وجود قيم مفقودة NA داخل الجدول، لا تتوقف ggplot2 عن العمل ولا ترمي استثناء يوقف البرنامج، بل تقوم بحذف الحالات المعطوبة تلقائياً مع إصدار تحذير ذكي (Informative Warning) يوضح عدد الصفوف المستبعدة بدقة: Removed X rows containing missing values (geom_point)، مما يحافظ على استمرارية التنفيذ البرمجي ويوثق في الوقت ذاته التعديلات الإحصائية المطبقة على البيانات.

11. البرمجة الدفاعية (Defensive Programming) وبناء أدوات فحص مخصصة

11.1 تطوير دوال تغليف مخصصة (Wrapper Functions) مع آليات تحقق مسبق

تعتبر البرمجة الدفاعية (Defensive Programming) المنهجية الاحترافية الأهم لتأمين خطوط الإنتاج الإحصائي (Data Pipelines) وتفادي ظهور الأخطاء المفاجئة أثناء المعالجة الآلية للبيانات الضخمة. يمكن للمحلل بناء دوال تغليف مخصصة (Custom Wrapper Functions) تحتوي على حواجز حماية مسبقة تتحقق من سلامة الأبعاد وتوافق الشروط الهندسية قبل تمرير البيانات إلى دوال الرسم الحساسة.

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

يمكن تصميم دالة فحص ذكية تقوم بالخطوات التالية:

  • قياس أطوال المتغيرات الداخلة وحساب الفارق المطلق بينها: diff_len <- abs(length(x) - length(y)).
  • إذا كان الفارق لا يساوي صفراً، تقوم الدالة بإطلاق تنبيه تشخيصي متقدم يوضح أن المتغير الأول يحمل طولاً مقداره $N_1$ بينما يحمل الثاني طولاً مقداره $N_2$ مع تحديد المتجه الأطول بدقة.
  • إتاحة خيار المعالجة الذاتية (Auto-remediation) من خلال توفير وسيط يتيح المواءمة التلقائية بالحذف المتبادل للقيم المفقودة أو تجميع المتغيرين قسرياً داخل data.frame عبر تطبيق na.omit() المشترك قبل استدعاء plot().

11.2 كتابة اختبارات الوحدات (Unit Testing) لتدفقات العمل الإحصائي

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

يتضمن بروتوكول اختبار الوحدات وضع اختبارات تأكيدية صارمة لمخرجات دوال تجهيز وتنظيف البيانات للتأكد من أنها تعيد دائماً مصفوفات ومتجهات متكافئة الأبعاد. يتم ذلك عبر صياغة اختبارات معيارية مثل expect_equal(length(output$x), length(output$y)) واختبارات التحقق من عدم وجود قيم مفقودة غير متناظرة expect_false(any(is.na(output$x) != is.na(output$y))).

تتيح أتمتة هذه الاختبارات لفرق البحث التأكد من أن التحديثات والتعديلات المدخلة على بروتوكولات استيراد وتصفية البيانات السلوكية لا تؤدي إلى كسر التوافق البعدي بين المتغيرات التابعة والمستقلة، مما يضمن تدفقاً سلساً وموثوقاً للتحليلات الإحصائية دون أي توقف مفاجئ في بيئات الإنتاج والتشغيل المستمر.

12. دليل إرشادي مرجعي لمنع تكرار الخطأ في بحوث علم النفس والقياس

12.1 قائمة التحقق المنهجية قبل استدعاء دوال الرسم في R

لضمان بيئة تحليلية خالية تماماً من أخطاء عدم تطابق المتجهات، يجب على الباحثين ومحللي البيانات اتباع قائمة التحقق المنهجية الصارمة التالية قبل استدعاء أي دالة رسم إحصائية:

  • التجميع الهيكلي المبكر: هل قمت بدمج كافة المتغيرات المستقلة والتابعة في إطار بيانات واحد (Single Data Frame) يحمل معرّفاً فريداً لكل مشارك؟
  • المعاينة البعدية الشاملة: هل قمت بفحص عدد صفوف المتغيرات باستخدام NROW() أو dim() والتأكد التام من تطابقها العددي قبل البدء في التحليل؟
  • المعالجة المتزامنة للقيم المفقودة: هل تم تنظيف القيم المفقودة NA على مستوى الجدول بأكمله عبر complete.cases() بدلاً من تطبيق na.omit() على كل عمود بصورة مستقلة؟
  • التناظر في التصفية واستبعاد الشواذ: هل طُبقت شروط الاستبعاد والمعايير الإحصائية (مثل تصفية أزمنة الرجع أو درجات المقاييس) على كافة المتغيرات في خطوة موحدة عبر الأقنعة المنطقية المشتركة؟
  • فحص سلامة الاستيراد الخارجي: هل تأكدت من خلو ملفات CSV و Excel من الأسطر والمسافات الوهمية في نهايات الأعمدة عبر ضبط وسائط القراءة الصحيحة؟

12.2 الملخص الإجرائي وخريطة اتخاذ القرار لحل المشكلة فور ظهورها

في حال ظهور رسالة الخطأ error in xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ أثناء تنفيذ التحليل، يُلخص المسار التنفيذي السريع للحل في ثلاث خطوات تصحيحية متسلسلة:

الخطوة الأولى (العزل والمعاينة البعدية): أوقف محاولات الرسم مؤقتاً، وافحص أطوال المتغيرات المستدعاة مباشرة عبر كتابة c(length(x), length(y)) في نافذة الأوامر لمعرفة أي المتجهين يحتوي على عناصر فائضة أو مفقودة وحجم الفارق الدقيق بينهما.

الخطوة الثانية (الكشف عن القيم المفقودة وإعادة الهيكلة): افحص وجود المفقودات عبر sum(is.na(x)) و sum(is.na(y)). إذا وُجدت مفقودات، أعد تجميع المتغيرين في جدول وطبق الحذف المتزامن: clean_data <- na.omit(data.frame(x = x, y = y))، ثم ارسم باستخدام plot(clean_data$x, clean_data$y).

الخطوة الثالثة (مراجعة شروط الفلترة والدمج): إذا كانت المتجهات خالية من NA ومع ذلك استمر تباين الأطوال، راجع الشيفرات السابقة للرسم وتأكد من أن المتغيرين لم يتم اشتقاقهما من مجموعات بيانات مختلفة دون استخدام دوال الربط المنهجية مثل merge() أو inner_join() بمفتاح تعريفي موحد.

خاتمة وخلاصة تركيبية

يمثل الخطأ error in xy.coords(x, y, xlabel, ylabel, log) : 'x' and 'y' lengths differ في بيئة لغة R الإحصائية علامة تحذيرية بنيوية صريحة تشير إلى فقدان التناغم الرياضي والتقابل الأحادي بين الإحداثيات الثنائية المراد تمثيلها في الفضاء الإحصائي. وكما أوضحنا في هذا الدليل الموسع، فإن هذا الخطأ ليس مجرد عائق تقني عابر، بل هو انعكاس لاختلالات أعمق قد تطال جمع البيانات، أو هيكلة ملفات الاستيراد، أو أساليب المعالجة غير المتناظرة للقيم المفقودة والحالات الشاذة في بحوث القياس والعلوم السلوكية.

إن تبني الممارسات البرمجية الرصينة—بدءاً من إدارة البيانات الموحدة داخل أطر البيانات المهيكلة، وتطبيق الحذف المتزامن عبر complete.cases()، واستخدام المرشحات المنطقية المشتركة، وصولاً إلى اعتماد البرمجة الدفاعية وبيئات الرسم الحديثة مثل ggplot2—يضمن تحصين التحليلات الإحصائية ضد الانهيار وتوفير تمثيل بصري دقيق وصادق يعكس البنية الحقيقية للظواهر المدروسة بأعلى معايير النزاهة العلمية.

References

اقتباس هذا المقال

looti, M. (2026, أغسطس 28). كيفية إصلاح: خطأ في xy.coords(x, y, xlabel, ylabel, log) : أطوال ‘x’ و ‘y’ مختلفة. عرب سايكلوجي. https://arabpsychology.com/statistics/how-to-fix-error-in-xy-coords-x-y-lengths-differ-in-r/
looti, Mohammed. “كيفية إصلاح: خطأ في xy.coords(x, y, xlabel, ylabel, log) : أطوال ‘x’ و ‘y’ مختلفة.” عرب سايكلوجي, 28 أغسطس 2026, https://arabpsychology.com/statistics/how-to-fix-error-in-xy-coords-x-y-lengths-differ-in-r/.
looti, Mohammed. “كيفية إصلاح: خطأ في xy.coords(x, y, xlabel, ylabel, log) : أطوال ‘x’ و ‘y’ مختلفة.” عرب سايكلوجي. أغسطس 28, 2026. https://arabpsychology.com/statistics/how-to-fix-error-in-xy-coords-x-y-lengths-differ-in-r/.