ما هي الحزمة
الحزمة رزمة من الدوال والوثائق وأحيانًا البيانات توسّع R. فـ R الأساسية تمنحك المتجهات والنماذج والمخططات؛ والحزم تمنحك كل ما عدا ذلك - و"كل ما عدا ذلك" هائل. وتستضيف CRAN (شبكة أرشيف R الشاملة) نحو 20,000 حزمة، كل واحدة منها مفحوصة باختبارات التقديم في CRAN قبل نشرها. وذلك المستودع هو السبب الرئيسي لبقاء R منافسة في العمل مع البيانات: فمهما كان التحليل، فقد حزمه أحدهم على الأرجح.
وCRAN ليست المصدر الوحيد - إذ تستضيف Bioconductor منظومة المعلوماتية الحيوية، ويقيم كثير من الحزم قيد التطوير على GitHub (وتُثبَّت بـ remotes::install_github()) - لكنك بوصفك مبتدئًا تستطيع اعتبار CRAN الافتراضية والبقية أشياء ستصادفها حين يخبرك ملف README بذلك.
وثمة قلة من الحزم تأتي مع R نفسها (مثل stats وutils وgraphics وأخواتها) وتُحمَّل تلقائيًا - ولهذا تعمل mean() وplot() ببساطة. وكل ما عداها يتبع طقس الخطوتين الذي سنتناوله.
install.packages() مرة واحدة، وlibrary() في كل جلسة
هذا هو الالتباس الأول لدى المبتدئين، فإليك أوضح صياغة ممكنة له. إن تشغيل حزمة عملان مختلفان بعمرين مختلفين:
install.packages("dplyr") # ONCE per machine: downloads from CRAN and installs
library(dplyr) # EVERY session: loads it so your code can use it
- الأمر
install.packages("dplyr")أشبه بشراء كتاب: تفعله مرة واحدة، ويبقى على رفك (قرصك) منذ ذلك الحين. ولاحظ علامتي الاقتباس - فأنت تمرر الاسم سلسلةً نصية. - والأمر
library(dplyr)أشبه بأخذ الكتاب من الرف: تفعله في بداية كل جلسة R (وعمليًا في مستهل كل نص برمجي). ولا حاجة إلى علامتي اقتباس هنا - فـlibrary()خاصة وتقبل الاسم المجرد (والصيغةlibrary("dplyr")تعمل أيضًا إن كنت تفضل الاتساق).
ونمطا الإخفاق يخبرانك بالخطوة التي تخطيتها. فالخطأ Error: there is no package called 'dplyr' من library() يعني أنها لم تُثبَّت قط. والخطأ Error: could not find function "filter" (أو "%>%") في منتصف نص برمجي يعني أن الحزمة مثبّتة لكن هذه الجلسة لم تحمّلها. ووضع كل استدعاء library() في مستهل النص البرمجي تمامًا - لا مبعثرًا فيه - يجعل الإخفاق الثاني مرئيًا في الثانية الأولى، ويؤدي في الوقت نفسه دور قائمة باعتماديات النص البرمجي. وتثبيت tidyverse يجري بالطريقة نفسها: install.packages("tidyverse") مرة واحدة، وlibrary(tidyverse) لكل جلسة، وهو ما يحمّل dplyr وggplot2 وبقية المجموعة الأساسية في سطر واحد.
وما لا ينبغي أن تفعله هو ترك install.packages() داخل نص برمجي تشغّله مرارًا أو تشاركه - فهو يعيد التنزيل في كل تشغيل وقد يفاجئ من ينفّذه. فالتثبيت فعل يخص الطرفية؛ والتحميل فعل يخص النص البرمجي.
الدالة require() والصيغة pkg::fun()
تبدو require() مرادفًا لـ library()، وإساءة استخدامها بهذا المعنى شائعة. والفرق هو ما يحدث حين تكون الحزمة مفقودة: فـ library() تتوقف بخطأ؛ بينما تطبع require() تحذيرًا وتعيد FALSE وتدع النص البرمجي يتابع - ليموت عادة بعد عشرين سطرًا برسالة "could not find function" المحيرة بدل الرسالة الصادقة "no package called". ولتحميل الاعتماديات، استخدم library(): فالإخفاق الصريح في المستهل ميزة. أما require() فلا تثبت جدارتها إلا في الفحوص الشرطية حيث تكون قيمتها المعادة هي المقصد:
if (!require(praise)) {
install.packages("praise")
library(praise)
}
وثمة طريقة لاستخدام حزمة دون تحميلها إطلاقًا: إذ يستدعي المعامل :: دالة واحدة بعنوانها الكامل بالصيغة package::function(). ويجب أن تكون الحزمة مثبّتة، لكن لا شيء يُلحق بجلستك:
(والحزمة stats تُحمَّل تلقائيًا على أي حال، فـ sd() المجردة تعمل كذلك - لكن الصياغة نفسها تنطبق على أي حزمة مثبّتة.) ويتألق المعامل :: في موضعين: الاستدعاءات العابرة التي يكون سطر library() كامل مبالغة لأجلها، وإزالة اللبس حين تصدّر حزمتان محمّلتان الاسم نفسه - والتصادم الكلاسيكي هو dplyr::filter() مقابل stats::filter().
إبقاء الحزم محدّثة
تتطور الحزم باستقلال عن R، فالتحديث مسؤوليتك:
update.packages() # offers to update everything outdated
update.packages(ask = FALSE) # same, without prompting per package
وثمة قاعدة غير بديهية: أن الحزم تُبنى مقابل إصدار رئيسي.فرعي محدد من R. فحين ترقّي R نفسها (من 4.3 إلى 4.4 مثلًا - راجع تثبيت R)، لا تُنقل مكتبة حزمك القديمة عمومًا، والحل هو ببساطة إعادة تثبيت الحزم التي تستخدمها تحت الإصدار الجديد. عشر دقائق من install.packages()، لا كارثة - لكنها تفاجئ الناس أول مرة تستقبل فيها نصوصهم البرمجية تثبيتًا جديدًا لـ R بجدار من أخطاء "no package called".
معرفة ما لديك
ثلاث دوال تجيب عن سؤال "ما المثبّت وأين":
installed.packages()[, "Version"] # every installed package with its version
sessionInfo() # R version + what THIS session has loaded
.libPaths() # the folders where packages are installed
تعيد installed.packages() مصفوفة بصف لكل حزمة - وعمود Version هو ما تريده عادة. والدالة sessionInfo() هي أداة قابلية إعادة الإنتاج: ألصق مخرجاتها في بلاغ عن علة فيعرف القارئ إصدار R لديك ونظام تشغيلك والإصدارات الدقيقة لكل حزمة محمّلة. وتعرض .libPaths() مجلدات المكتبات التي تبحث فيها R؛ ومعرفة وجودها تزيل الغموض عن سؤال "أين ذهبت تلك الحزمة فعلًا؟" ولماذا تهم صلاحيات المدير أحيانًا على الأجهزة المشتركة.
حزم جديرة بالمعرفة
لست بحاجة إليها اليوم، لكنك ستصادفها باستمرار - ومعرفة الغرض من كل واحدة تساعدك على قراءة شيفرة الآخرين:
- dplyr - أفعال معالجة البيانات:
filterوmutateوgroup_byوsummarize. - ggplot2 - حزمة الرسم القياسية؛ ومعظم رسوم R التي تراها على الإنترنت من ggplot2.
- tidyr - إعادة تشكيل البيانات بين الصيغتين العريضة والطويلة (
pivot_longerوpivot_wider). - readr / readxl - قراءة CSV السريعة وقراءة ملفات Excel على الترتيب.
- lubridate - تواريخ تتصرف كما تتوقع.
- stringr - معالجة متسقة للسلاسل النصية.
- data.table - منظومة بديلة عالية الأداء لإطارات البيانات؛ ولهجة مختلفة عن tidyverse، محبوبة في البيانات الضخمة.
- shiny - تطبيقات ويب تفاعلية مكتوبة بالكامل بلغة R.
والست الأولى هي نواة tidyverse وتصل معًا عبر install.packages("tidyverse"). ولا إلزام باستخدام أي منها - فـ R الأساسية قادرة على كل ذلك - لكن المنظومة هي المكان الذي تقيم فيه معظم شيفرة R الحديثة.
ما تخرج به
- تستضيف CRAN نحو 20,000 حزمة مدققة؛ وتغطي Bioconductor وGitHub البقية.
- الأمر
install.packages("name")مرة واحدة لكل جهاز (وعلامتا الاقتباس مطلوبتان)؛ والأمرlibrary(name)مرة واحدة لكل جلسة، في مستهل النص البرمجي. - تخفق
library()بصوت مرتفع - وهذا جيد؛ وتعيدrequire()القيمةFALSE- وهي مفيدة داخل الفحوص فقط. - تستخدم الصيغة
pkg::fun()دالة واحدة دون إلحاق الحزمة، وتحل تصادمات الأسماء. - تبقي
update.packages()الأمور محدّثة؛ وترقية R الرئيسية تعني إعادة تثبيت الحزم. - والدالة
sessionInfo()هي وسيلتك لإخبار أحدهم (أو نفسك مستقبلًا) بالبيئة التي عملت عليها شيفرتك بالضبط.
التالي: دليل العمل - أين تبحث R عن الملفات، ولماذا يكون ذلك أول ما ينبغي فحصه حين تفشل قراءة البيانات.
الأسئلة الشائعة
كيف أثبّت حزمة في R؟
نفّذ install.packages("name") مع اسم الحزمة بين علامتي اقتباس، مثل install.packages("dplyr"). فتنزّلها R من CRAN وتثبّتها على جهازك. وتفعل ذلك مرة واحدة لكل جهاز - وبعدها حمّلها في كل جلسة بالأمر library(dplyr).
ما الفرق بين install.packages() وlibrary()؟
ينزّل install.packages("dplyr") الحزمة إلى حاسوبك - مرة واحدة لكل جهاز. ويحمّل library(dplyr) حزمة مثبّتة بالفعل إلى الجلسة الحالية - مرة واحدة لكل جلسة، وعادة في مستهل كل نص برمجي. والتثبيت دون تحميل لا يعطيك شيئًا صالحًا للاستعمال؛ والتحميل دون تثبيت يطلق الخطأ "there is no package called 'dplyr'".
ما الفرق بين library() وrequire() في R؟
كلتاهما تحمّل حزمة، لكن عند الإخفاق تتوقف library() بخطأ بينما تكتفي require() بتحذير وتعيد FALSE. وهذا يجعل library() مناسبة للنصوص البرمجية - إخفاق صريح ومبكر - ويجعل require() مفيدة فقط داخل فحوص شرطية مثل if (!require(pkg)) install.packages(pkg).