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

ما هي قائمة R؟
قائمة R هو كائن في برمجة R يتضمن مصفوفات أو نواقل أو إطارات بيانات أو قوائم بداخلها. تُستخدم قائمة R أيضًا لتخزين مجموعة من الكائنات واستخدامها عندما نحتاج إليها. يمكننا أن نتخيل قائمة R كحقيبة لوضع العديد من العناصر المختلفة. عندما نحتاج إلى استخدام أحد العناصر، يمكننا فتح الحقيبة واستخدامها.
يكمن الفرق بين هذه الحقيبة والمتجه في كونها أداة مفيدة. فالمتجه يُجبر كل عنصر على أن يكون من نوع واحد، لذا فإن وضع كلمة بجانب رقم يحول الرقم إلى نص. أما القائمة فلا تخضع لمثل هذه القاعدة، ولهذا السبب يمكنها استيعاب متجه من خمسة عناصر، أو صفين. البخور وإطار بيانات مكون من 714 صفًا جنبًا إلى جنب دون تغيير أي منها.
بناء جملة القائمة في R
يمكننا استخدام الدالة list() لإنشاء قوائم في لغة البرمجة R:
list(element_1, ...) arguments: -element_1: store any type of R object -...: pass as many objects as specifying. each object needs to be separated by a comma
يمكن تمرير كل وسيط بشكل مباشر أو بالشكل التالي العلامة = القيمةيصبح الوسيط المجرد عنصرًا موضعيًا لا يمكن الوصول إليه إلا برقمه، بينما يكتسب الوسيط الموسوم اسمًا أيضًا. مرجع R الأساسي لـ قائمة() يوثق كلا الشكلين ويشير إلى أن unlist() يعمل كمعكوس تقريبي لـ as.list().
كيفية إنشاء قائمة في R
فيما يلي عملية خطوة بخطوة حول كيفية إنشاء قائمة في R:
في المثال أدناه، سنقوم بإنشاء ثلاثة كائنات مختلفة، Vector، وMatrix، وa إطار البيانات باستخدام وظيفة القائمة في R.
الخطوة 1) إنشاء ناقل
استخدم الكود أدناه لإنشاء متجه في R
# Vector with numeric from 1 up to 5
vect <- 1:5
يقوم عامل النقطتين ببناء التسلسل 1، 2، 3، 4، 5 كمتجه عدد صحيح، ويقوم سهم التعيين بتخزينه تحت اسم vect.
الخطوة 2) إنشاء مصفوفة
الآن، أنشئ مصفوفة باستخدام الكود التالي
# A 2x 5 matrix
mat <- matrix(1:9, ncol = 5)
dim(mat)
هناك تفصيلان جديران بالملاحظة هنا. تحتاج شبكة مكونة من صفين وخمسة أعمدة إلى عشر قيم، ولكن لم يتم توفير سوى تسع قيم، لذا يعيد برنامج R استخدام التسلسل ويطبع تحذيرًا بأن طول البيانات ليس من مضاعفات عدد الصفوف. هذه القيمة المعاد استخدامها هي سبب انتهاء الصف الثاني من المصفوفة المطبوعة بالرقم 1 بدلاً من 10. ثم يُبلغ استدعاء الدالة dim() عن شكل الشبكة.
الإخراج:
## [1] 2 5
الخطوة 3) إنشاء إطار البيانات
قم بإنشاء إطار بيانات في R باستخدام الكود أدناه
# select the 10th row of the built-in R data set EuStockMarkets
df <- EuStockMarkets[1:10,]
يشير التعليق إلى الصف العاشر، لكن التعبير يحتفظ بالصفوف من 1 إلى 10 من سلسلة EuStockMarkets المدمجة. كما أن عملية التحديد الجزئي تحذف فئة السلسلة الزمنية، لذا فإن الناتج هو مصفوفة رقمية وليست إطار بيانات حقيقي، وهذا تحديدًا سبب احتواء النتيجة المطبوعة أدناه على تسميات صفوف على شكل [1,] بدلًا من أسماء الصفوف. استخدم الدالة as.data.frame() عند الحاجة إلى إطار بيانات حقيقي.
الخطوة 4) إنشاء قائمة في R
الآن، يمكننا وضع الكائنات الثلاثة في قائمة R باستخدام الكود أدناه
# Construct list with these vec, mat, and df:
my_list <- list(vect, mat, df)
my_list
الإخراج:
## [[1]] ## [1] 1 2 3 4 5 ## [[2]] ## [,1] [,2] [,3] [,4] [,5] ## [1,] 1 3 5 7 9 ## [2,] 2 4 6 8 1 ## [[3]] ## DAX SMI CAC FTSE ## [1,] 1628.75 1678.1 1772.8 2443.6 ## [2,] 1613.63 1688.5 1750.5 2460.2 ## [3,] 1606.51 1678.6 1718.0 2448.2 ## [4,] 1621.04 1684.1 1708.1 2470.4 ## [5,] 1618.16 1686.6 1723.1 2484.7 ## [6,] 1610.61 1671.6 1714.3 2466.8 ## [7,] 1630.75 1682.9 1734.5 2487.9 ## [8,] 1640.17 1703.6 1757.4 2508.4 ## [9,] 1635.47 1697.5 1754.0 2510.5 ## [10,] 1645.89 1716.3 1754.3 2497.4
تمثل العناوين الثلاثة بين قوسين مزدوجين في هذا الناتج مواقع القائمة. لم يتم تسطيح أي شيء أو تحويله: العنصر الأول لا يزال متجهًا عدديًا صحيحًا، والعنصر الثاني لا يزال مصفوفة، والعنصر الثالث لا يزال يحتوي على جميع صفوف أسعار الأسهم العشرة.
حدد عناصر من قائمة R
بعد إنشاء قائمتنا، يُمكننا الوصول إليها بسهولة. نحتاج إلى استخدام [[index]] لتحديد عنصر في القائمة. القيمة الموجودة داخل القوسين المربعين المزدوجين تُمثل موضع العنصر في القائمة التي نريد الوصول إليها.tracعلى سبيل المثال، إذا مررنا الرقم 2 داخل الأقواس، فإن R تُرجع العنصر الثاني المدرج.
الآن في هذا البرنامج التعليمي Rفلنحاول تحديد العنصر الثاني من القوائم في R المسمى my_list، نستخدم my_list[[2]]
# Print second element of the list
my_list[[2]]
الإخراج:
## [,1] [,2] [,3] [,4] [,5] ## [1,] 1 3 5 7 9 ## [2,] 2 4 6 8 1
لا يمكن استبدال الأقواس المفردة والمزدوجة، والخلط بينهما هو السبب الأكثر شيوعًا لأخطاء القوائم. القوس الواحد يُبقي على العنصر المُغلِّف، بينما القوسان المزدوجان يُزيلانه.
| التعبير | ما الذي سيعود؟ | فئة النتيجة | استخدمه عندما |
|---|---|---|---|
| my_list[[2]] | العنصر المخزن نفسه | مهما كان ما تم تخزينه، هنا مصفوفة | عليك إجراء عملية حسابية على عنصر واحد |
| my_list[2] | قائمة فرعية تحتوي على ذلك العنصر الواحد | الإدارية | يجب عليك الاحتفاظ بغلاف القائمة |
| my_list[c(1, 3)] | قائمة فرعية بالعناصر المختارة | الإدارية | أنت بحاجة إلى عدة عناصر في وقت واحد |
| my_list[-2] | كل عنصر باستثناء العنصر الثاني | الإدارية | عليك حذف عنصر |
# Compare the two bracket styles class(my_list[[2]]) # the matrix itself class(my_list[2]) # a list of length one # Several elements, and everything but one element my_list[c(1, 3)] my_list[-2]
القوائم المسماة في لغة R
تُعدّ الفهارس الموضعية هشة: فعند إدخال عنصر واحد، يتحرك كل رقم يليه. يُزيل تسمية العناصر هذا الخطر، ويجعل الكود متوافقًا مع البيانات التي يصفها. يمكن تحديد الأسماء عند إنشاء القائمة، أو إضافتها لاحقًا باستخدام الدالة names().
# Tag each element at creation time named_list <- list(numbers = vect, grid = mat, prices = df) # Three ways to reach the same element named_list$grid named_list[["grid"]] named_list["grid"] # returns a one-element list # Read or replace the names later names(named_list) names(named_list)[2] <- "grid_2x5"
يختلف عامل $ والأقواس المزدوجة في جانب واحد يُوقع المبتدئين في الخطأ. يُجري عامل $ مطابقة جزئية، لذا فإن named_list$pri لا يزال يجد الأسعار، بينما تُرجع named_list[[“pri”]] قيمة NULL لأن الأقواس المزدوجة تُطابق تمامًا ما لم يتم تمرير exact = FALSE. تُعدّ المطابقة الجزئية مُريحة في سطر الأوامر، ولكنها غير آمنة في البرامج النصية، لذا يُفضّل استخدام الصيغة الدقيقة في الكود المحفوظ.
# A compact map of the whole structure
str(named_list)
تقوم الدالة str() بطباعة سطر واحد لكل عنصر مع نوعه وحجمه، وهي أسرع طريقة للتأكد من أن القائمة تحتوي على ما تتوقعه قبل الوصول إلى عناصرها.
تعديل وإضافة وحذف العناصر في قائمة R
لا تُعتبر القائمة ثابتة بمجرد إنشائها. فنفس الدوال التي تقرأ عنصرًا ما هي التي تكتب إليه أيضًا، لذا فإن تحديث القائمة وتوسيعها وتقليصها كلها تستخدم عملية إسناد عادية.
# Replace an element in place named_list[["numbers"]] <- 1:10 # Add a new element simply by naming it named_list[["created"]] <- Sys.Date() # Append without a name: the element lands at the end named_list <- append(named_list, list(TRUE)) # Delete an element by assigning NULL to it named_list[["created"]] <- NULL
- يحل محل: يؤدي تعيين اسم موجود إلى استبدال ذلك العنصر وترك موضعه دون تغيير.
- إضافة: يؤدي تعيين اسم غير موجود إلى إضافة عنصر جديد في نهاية القائمة.
- ألحق: تأخذ الدالة append() قائمة كمعامل ثانٍ، لذا قم بتغليف القيمة المجردة في list() قبل تمريرها.
- حذف: يؤدي تعيين قيمة NULL باستخدام الأقواس المزدوجة إلى إزالة العنصر وتقصير القائمة.
إحدى النتائج التي يقع فيها المستخدمون بشكل متكرر: بما أن NULL تعني الحذف، فلا يمكنك تخزين قيمة NULL فعلية باستخدام الأقواس المزدوجة. استخدم بدلاً من ذلك التعيين باستخدام قوس واحد، كما في named_list[“empty”] <- list(NULL)، والذي يحتفظ بالخانة ويضع NULL بداخلها.
القوائم المتداخلة ودالة unlist() في لغة R
بما أن القائمة يمكنها استيعاب أي كائن R، فيمكنها استيعاب قائمة أخرى. يُعد التداخل الطريقة التي تُمثل بها كائنات التكوين، واستجابات JSON، ونتائج النماذج عادةً في R، لذا فإن الوصول إلى قائمة متداخلة وتسطيحها من المهام اليومية.
# A list whose elements are themselves lists project <- list( meta = list(owner = "analyst", year = 2026), data = list(vect, mat) ) # Chain the accessors to reach an inner value project$meta$year project[["data"]][[2]] # Flatten every level into one atomic vector flat <- unlist(project) # Strip a single level and keep the rest as a list half <- unlist(project, recursive = FALSE)
للتسطيح تكلفةٌ تستحق الفهم. يجب أن تُعيد الدالة unlist() متجهًا واحدًا، لذا فهي تُحوّل كل قيمة إلى النوع الأكثر عموميةً الموجود، وفقًا للترتيب التالي: منطقي، عدد صحيح، عدد عشري، حرفي. وبالتالي، فإن القائمة المتداخلة التي تمزج الأرقام بالنصوص تُعاد كنصٍّ بالكامل. تُبنى أسماء النتائج بدمج الوسوم الخارجية والداخلية، ولهذا السبب يصل العنصر كـ meta.owner بدلًا من owner.
استخدم `use.names = FALSE` عندما تكون الأسماء المركبة غير مرغوب فيها، واضبط `recursive = FALSE` عندما تريد إزالة الطبقة الخارجية فقط. إذا كان يجب الاحتفاظ بأنواع القيم، فاترك البنية سليمة وتعامل مع القائمة بدلاً من تسطيحها.
إطار بيانات مدمج في R
غالبًا ما تُملأ القوائم ببيانات مقروءة من القرص أو من الإنترنت، لذا من المفيد معرفة كيفية وصول إطار البيانات قبل تخزينه داخلها. قبل إنشاء إطار بيانات خاص بنا، يمكننا إلقاء نظرة على مجموعة بيانات R المتاحة عبر الإنترنت. تتكون مجموعة بيانات السجن من 714×5 أبعاد. يمكننا إلقاء نظرة سريعة على الجزء السفلي من إطار البيانات باستخدام الدالة tail(). وبالمثل، تعرض الدالة head() الجزء العلوي من إطار البيانات. يمكنك تحديد عدد الصفوف المعروضة باستخدام head(df, 5). سنتعرف على المزيد حول الدالة read.csv() في... استيراد البيانات في R البرنامج التعليمي.
PATH <-'https://raw.githubusercontent.com/guru99-edu/R-Programming/master/prison.csv'
df <- read.csv(PATH)[1:5]
head(df, 5)
الإخراج:
## X state year govelec black ## 1 1 1 80 0 0.2560 ## 2 2 1 81 0 0.2557 ## 3 3 1 82 1 0.2554 ## 4 4 1 83 0 0.2551 ## 5 5 1 84 0 0.2548
يُحدد الجزء [1:5] الذي يلي استدعاء الدالة read.csv() الأعمدة الخمسة الأولى، وليس الصفوف الخمسة الأولى، لأن إطار البيانات هو في حد ذاته قائمة من الأعمدة. يؤدي استخدام فهرسة الأقواس المفردة على قائمة إلى إرجاع قائمة أصغر، وهذه القائمة الأصغر هي أيضاً إطار بيانات.
يمكننا التحقق من بنية إطار البيانات باستخدام str:
# Structure of the data
str(df)
الإخراج:
## 'data.frame': 714 obs. of 5 variables: ## $ X : int 1 2 3 4 5 6 7 8 9 10 ... ## $ state : int 1 1 1 1 1 1 1 1 1 1 ... ## $ year : int 80 81 82 83 84 85 86 87 88 89 ... ## $ govelec: int 0 0 1 0 0 0 1 0 0 0 ... ## $ black : num 0.256 0.256 0.255 0.255 0.255 ...
يتم تخزين كافة المتغيرات في عددي التنسيق. البادئة $ في كل سطر هي نفس المعامل المستخدم في القوائم المسماة سابقًا، مما يؤكد أن إطار البيانات عبارة عن قائمة من الأعمدة متساوية الطول تحمل تسمية مستطيلة. وبالتالي، فإن كل ما تعلمناه عن تسمية عناصر القائمة وتحديدها وحذفها ينتقل مباشرةً إلى أنواع بيانات R وإلى أعمدة إطار البيانات.
