كل شيء في R متجه
معظم اللغات تملك قيمًا قياسية - قيمًا مفردة - ثم نوعًا حاويًا لحفظ عدة قيم منها. أما R فتتخطى القيمة القياسية. فالمتجه مجموعة مرتبة من القيم تتشارك كلها نوعًا واحدًا، وهو الوحدة التي يُبنى عليها كل شيء آخر. وحتى ما يبدو عددًا منفردًا هو متجه بطول 1:
الدالة c() - اختصار combine أي الدمج - هي وسيلتك لبناء متجه يدويًا. وتخبرك length() بعدد العناصر التي يحملها. والقيمة 5 وحدها تعطي is.vector النتيجة TRUE بطول 1: فـ R لا تكف يومًا عن العمل بالمتجهات، بل تعمل أحيانًا بمتجهات قصيرة جدًا.
وهذا التصميم هو سبب اختلاف شيفرة R عن Python أو JavaScript: فالعمليات التي تكتب لها حلقة في مكان آخر تنطبق على متجهات كاملة في تعبير واحد. وسنصل إلى ذلك بعد قليل.
وثمة قاعدة ينبغي استيعابها الآن: كل عناصر المتجه من النوع نفسه. فإذا سلّمت c() خليطًا، لم تعترض - بل حوّلت كل شيء بصمت إلى أكثر الأنواع مرونة بين الموجودة:
فسلسلة نصية واحدة في الخليط تحوّل كل شيء إلى نصوص ("1" و"TRUE"). والقيم المنطقية بين الأرقام تصير 1 و0. وهذا الإكراه يتبع تراتبية ثابتة - logical ← integer ← double ← character - ويحدث دون تحذير، ولهذا يمكن لقيمة "7" شاردة في عمود من الأرقام أن تحوّل مجموعة بياناتك كلها إلى نص بهدوء. والتراتبية الكاملة مشروحة في أنواع البيانات؛ وإذا احتجت إلى حفظ قيم مختلطة فعلًا، فذلك ما وُجدت القوائم لأجله.
توليد المتتاليات: النقطتان الرأسيتان وseq() وrep()
كتابة كل عنصر داخل c() تصبح مملة بسرعة. وتملك R ثلاثة اختصارات للأنماط المنتظمة:
- التعبير
1:10هو الأداة اليومية: أعداد صحيحة من حد إلى آخر بخطوات مقدارها 1. - وتعمم
seq()ذلك: اختر الخطوة بالوسيطby =، أو حدد عدد العناصر التي تريدها بالوسيطlength.out =ودع R تحسب التباعد. - وتنتج
seq_len(n)القيم من1إلىnوهي الطريقة الآمنة لبناء فهارس الحلقات - فبخلاف1:n، تعطي متجهًا فارغًا بشكل صحيح حين تكونnصفرًا بدل العدّ التنازلي1 0. - وتكرر
rep(): فالوسيطtimes =يكرر المتجه كاملًا تباعًا (1 2 1 2 1 2)، والوسيطeach =يكرر كل عنصر في موضعه (1 1 1 2 2 2). ويسهل الخلط بينهما؛ فشغّل المقتطف وقارن.
الفهرسة: R تعدّ من 1
تسحب الأقواس المربعة العناصر. والعنصر الأول هو [1] لا [0]. وإذا كنت قادمًا من Python أو JavaScript، فهذه هي العثرة المبكرة الأكثر شيوعًا:
وثمة ثلاثة أمور تستحق التوقف عندها:
- يمكنك الفهرسة بـ متجه من المواضع - فالتعبير
fruits[c(2, 4)]يلتقط الثاني والرابع دفعة واحدة. - الفهارس السالبة تعني "كل شيء باستثناء". فالتعبير
fruits[-1]هو المتجه دون عنصره الأول. وهذا مختلف تمامًا عن Python حيث يعني-1العنصر الأخير. ولا يمكنك خلط الفهارس الموجبة والسالبة في الاستدعاء نفسه. - التعبير
fruits[0]ليس خطأ - بل يعيدcharacter(0)فارغًا. وعلة فرق الواحد في R تنتج غالبًا نتائج فارغة صامتة بدل انهيار، لذا يُستحسن فحصlength()حين يبدو شيء لاحق فارغًا على نحو غامض.
ويمكن للعناصر أن تحمل أسماء أيضًا، وهو ما يمنحك طريقة ثالثة للفهرسة - بالتسمية:
وتعمل المتجهات المسماة مثل جدول بحث خفيف وتبقي الشيفرة مقروءة: فالتعبير prices["tea"] يقول ما يعنيه، بينما prices[2] لا يقول.
الأقنعة المنطقية والدالة which()
أقوى طرق الفهرسة هي بمتجه منطقي - قناع من قيم TRUE/FALSE بطول البيانات نفسه. وكل مقارنة على متجه تنتج ذلك بالضبط:
فالتعبير temps > 24 لا يعطي جوابًا واحدًا - بل يعطي خمسة، واحدًا لكل عنصر. ووضع ذلك القناع داخل [ ] يبقي العناصر التي يكون القناع عندها TRUE. وادمج الشروط بالمعامل & (و) والمعامل | (أو)، وهما مشروحان مع بقية المعاملات.
وتترجم which() القناع إلى مواضع: وهي هنا 2 3 5، أي فهارس القراءات الحارة. الجأ إليها حين تحتاج إلى معرفة أين تقع المطابقات - لتقريرها، أو لفهرسة متجه آخر عند المواضع نفسها. أما للترشيح البسيط، فالتعبير temps[temps > 24] أكثر مباشرة من temps[which(temps > 24)].
ونمط الترشيح بالقناع هذا هو العمود الفقري لكل العمل مع البيانات في R تقريبًا - وسيعود مباشرة حين ترشّح صفوف إطار بيانات.
الحساب المتجهي وقاعدة إعادة التدوير
تنطبق العمليات الحسابية في R عنصرًا عنصرًا على متجهات كاملة - دون أي حلقة:
والسطر الأول هو الميزة الأبرز: فالتعبير prices * 2 يضاعف كل عنصر. وحيث تحتاج لغات أخرى إلى حلقة for، تحتاج R إلى معامل - والصيغة المتجهية أقصر وأسرع معًا، لأن التكرار يجري في شيفرة C محسّنة تحت السطح. اكتب حلقة for حين تعتمد كل خطوة على سابقتها؛ أما للحساب عنصرًا عنصرًا، فوجّه العملية متجهيًا.
ويعرض السطر الثالث قاعدة إعادة التدوير: فحين يختلف طول المتجهين، تكرر R الأقصر ليطابق. فيُعاد تدوير c(10, 20) ليصبح 10 20 10 20، فتكون النتيجة 11 22 13 24. وإعادة تدوير القيمة 2 عبر متجه بطول 3 هي بالضبط ما جعل prices * 2 يعمل - فالقيمة القياسية ليست إلا متجهًا بطول 1 يُعاد تدويره.
وإعادة التدوير نظيفة حين يكون الطول الأطول مضاعفًا دقيقًا للأقصر. وحين لا يكون كذلك، تحسب R النتيجة رغم ذلك - وتصدر تحذيرًا:
فتحصل على 11 22 13 مع تحذير بأن طول الكائن الأطول ليس مضاعفًا لطول الكائن الأقصر. عامل ذلك التحذير بوصفه بلاغًا عن علة: فإعادة التدوير الجزئية لا تكون تقريبًا ما قصدته أبدًا، وهي تعني عادة أن متجهين كان ينبغي أن يتساوى طولهما لم يتساويا.
الترتيب والعكس وإزالة التكرار
ثلاث أدوات صغيرة ستستخدمها باستمرار:
ترتب sort() القيم، وتقلب rev() الترتيب القائم دون فرز، وتسقط unique() المكررات مع الإبقاء على أول ظهور. ولا تعدّل أي منها المتجه x - فمثل كل شيء في R تقريبًا، تعيد متجهًا جديدًا وتترك الأصل وشأنه.
ما تخرج به
- المتجه هو الوحدة الأساسية في R: مرتب، وبنوع واحد في كل عناصره، وحتى القيم المفردة متجهات بطول 1.
- ابنِ بـ
c()، وولّد الأنماط بالنقطتين الرأسيتين وseq()وrep()- وتذكر أنc()تكره الأنواع المختلطة بصمت. - تبدأ الفهرسة من 1؛ والفهارس السالبة تسقط العناصر؛ وتتيح الأسماء الفهرسة بالتسمية.
- الأقنعة المنطقية (
x[x > 5]) هي صيغة الترشيح في اللغة كلها؛ وتحوّلwhich()القناع إلى مواضع. - الحساب متجهي، والمتجهات الأقصر يُعاد تدويرها، وتحذير إعادة التدوير الجزئية يعني أن لديك علة.
التالي: القوائم - الحاوية المناسبة حين لا تتشارك قيمك نوعًا واحدًا.
الأسئلة الشائعة
كيف تنشئ متجهًا في R؟
بالدالة c() (اختصار combine أي الدمج): x <- c(10, 20, 30). وللمتتاليات المنتظمة، استخدم 1:10 أو seq(0, 1, by = 0.25) أو rep(0, 5). ويجب أن ينتهي كل عنصر إلى النوع نفسه - فإذا خلطت الأنواع، حوّلتها R كلها بصمت إلى أكثرها مرونة.
هل تبدأ الفهرسة في R من 0 أم من 1؟
من 1. فالتعبير x[1] هو العنصر الأول، وx[length(x)] هو الأخير. وهذا يربك كل قادم من Python أو JavaScript أو C - إذ لا وجود للعنصر x[0] (وطلبه يعيد متجهًا فارغًا لا خطأ، وهو ما يجعل العلة صامتة).
ماذا تفعل قاعدة إعادة التدوير في R؟
حين تجري عملية حسابية على متجهين مختلفي الطول، تكرر R الأقصر حتى يطابق الأطول. فالتعبير c(1, 2, 3, 4) + c(10, 20) يعطي 11 22 13 24. وإذا لم يكن الطول الأطول مضاعفًا للأقصر، فإن R تحسب النتيجة رغم ذلك لكنها تصدر تحذيرًا - وعامل ذلك التحذير بوصفه علة.
ماذا تفعل الدالة which() في R؟
تحوّل متجهًا منطقيًا إلى مواضع قيمه TRUE. فإذا أعطى x > 5 النتيجة FALSE TRUE TRUE، فإن which(x > 5) تعطي 2 3. استخدمها حين تحتاج إلى المواضع نفسها؛ أما للترشيح البسيط فالفهرسة بالمتجه المنطقي مباشرة (x[x > 5]) أبسط.