أحد تلك الأمور المزعجة التي نحاول جميعًا فهمها عندما نتعلم Pandas هو التمييز بين .loc
و .iloc
.
لنضع حدًا لهذا الالتباس ونوضح الفرق بين هذين الأسلوبين. سأقدم العديد من الأمثلة، وآمل أن يكون التمييز أكثر وضوحًا بنهاية هذه المدونة.
ما هي .loc و .iloc في Pandas؟
كل من .loc
و .iloc
هما سمتان أساسيتان لإطارات البيانات في Pandas، وكلاهما يستخدمان لتحديد مجموعات فرعية محددة من البيانات. الغرض منهما هو الوصول إلى جزء معين من إطار البيانات وتمكين تلاعبه بدلاً من الوصول إلى الإطار بأكمله.
ميزة |
.loc |
.iloc |
الصيغة |
df.loc[row_indexer, column_indexer] |
df.iloc[row_indexer, column_indexer] |
طريقة الفهرسة |
الفهرسة بناءً على التسمية |
الفهرسة بناءً على الموقع |
تستخدم للإشارة |
تسميات الصفوف والأعمدة |
الفهرس الرقمي للصفوف والأعمدة (ابتداءً من 0) |
كما يمكننا رؤية من الجدول، يبدو البناء متشابهًا للغاية. الاختلاف يكمن في كيفية استخدام وسيطات row_indexer
و column_indexer
. هذا يرجع إلى أن الطريقتين تقدمان نهجين مختلفين للفهرسة: بينما تقوم .loc
بالفهرسة بناءً على تسميات الصفوف، فإن .iloc
يأخذ الفهرس الرقمي للصفوف والأعمدة كوسيطات.
لنفحص كلتا الطريقتين بتفصيل، نبدأ بـ .loc
.
باستخدام .loc: الاختيار بواسطة التسميات
لتوضيح المفاهيم، دعنا نفترض قاعدة بيانات العملاء الافتراضية الممثلة بواسطة هذه الإطار البيانات يسمى df
، مع معرف العميل
الذي يمثل الفهرس الصف index:
معرف العميل |
الاسم |
البلد |
المنطقة |
العمر |
C123 |
جون دو |
الولايات المتحدة |
أمريكا الشمالية |
67 |
C234 |
بيتر مولر |
ألمانيا |
أوروبا |
51 |
C345 |
علي خان |
باكستان |
آسيا |
19 |
C456 |
ماريا غونزاليس |
المكسيك |
شمال أمريكا |
26 |
C567 |
ديفيد لي |
الصين |
آسيا |
40 |
هناك أربع طرق رئيسية لتحديد الصفوف باستخدام .loc
. وتشمل:
- تحديد صف واحد
- تحديد صفوف متعددة
- تحديد شريحة من الصفوف
- تحديد الصفوف بشكل شرطي
تحديد صف واحد باستخدام .loc
لتحديد صف واحد، نستخدم تسمية الصف الذي نريد استرجاعه كـ row_indexer
. وبالتالي، تبدو الصيغة كالتالي: df.loc['row_label']
. لنستخدم هذا لعرض جميع المعلومات عن عميلنا علي خان:
df.loc['C345']
C345 |
|
اسم |
علي خان |
البلد |
باكستان |
المنطقة |
آسيا |
العمر |
19 |
اختيار عدة صفوف باستخدام .loc
إذا أردنا اختيار عدة صفوف لا تتبع بالضرورة بعضها البعض بالترتيب، يجب علينا تمرير قائمة بعناوين صفوفها كوسيط row_indexer
. هذا يعني أننا بحاجة لاستخدام زوجين من الأقواس المربعة: واحد للتركيب العادي .loc
وآخر لقائمة العناوين.
السطر df.loc[['row_label_1', 'row_label_2']]
سيعيد الصفين من إطار البيانات df
المحددين في القائمة. لنفترض أننا أردنا معرفة المعلومات ليس فقط عن علي خان ولكن أيضًا عن ديفيد لي:
df.loc[['C345', 'C567']]
معرف العميل |
الاسم |
الدولة |
المنطقة |
العمر |
C345 |
علي خان |
باكستان |
آسيا |
19 |
C567 |
ديفيد لي |
الصين |
آسيا |
40 |
اختيار شريحة من الصفوف باستخدام .loc
يمكننا تحديد مجموعة من الصفوف عن طريق تمرير علامات الصف الأولى والأخيرة مع علامة الاقتسام بينهما: df.loc['علامة_بداية_الصف':'علامة_نهاية_الصف']
. يمكننا عرض أول أربع صفوف في إطار البيانات الخاص بنا بهذه الطريقة:
df.loc['C123' : 'C456']
معرّف العميل |
الاسم |
البلد |
المنطقة |
تاريخ التسجيل |
C123 |
جون دو |
الولايات المتحدة |
أمريكا الشمالية |
67 |
C234 |
بيتر مولر |
ألمانيا |
أوروبا |
51 |
C345 |
علي خان |
باكستان |
آسيا |
19 |
C456 |
ماريا غونزاليس |
المكسيك |
أمريكا الشمالية |
26 |
هناك أمران يجب أن تضعهما في الاعتبار هنا:
- يتضمن الناتج الصف المحدد في
row_label_end
. وهذا يختلف في.iloc
، والذي سنتناوله لاحقًا. - نستخدم زوجًا واحدًا فقط من الأقواس المربعة، على الرغم من أننا نريد استرجاع عدة صفوف. نحن لا نستخدم قائمة لتحديد الصفوف المختلفة، لذا فإن استخدام قوسي مربعين سيؤدي إلى
SyntaxError
.
اختيار الصفوف بشكل شرطي باستخدام .loc
يمكننا أيضًا إرجاع الصفوف بناءً على تعبير شرطي. يمكننا تصفية جميع الصفوف بناءً على ما إذا كانت تحقق شرطًا معينًا أم لا، وعرض الصفوف التي تحقق ذلك فقط.
البنية النحوية المقابلة هي df.loc[conditional_expression]
، حيث يكون conditional_expression
عبارة عن بيان حول القيم المسموح بها في عمود معين.
بالنسبة للأعمدة التي تحتوي على بيانات غير رقمية (مثل الاسم
أو البلد
)، يمكن للجملة استخدام عامل المساواة أو عدم المساواة فقط، لأنه لا يوجد ترتيب بين القيم. يمكننا، على سبيل المثال، إرجاع جميع صفوف العملاء الذين ليسوا من آسيا:
df.loc[df['Region'] != 'Asia']
معرف العميل |
الاسم |
البلد |
المنطقة |
العمر |
C123 |
جون دو |
الولايات المتحدة |
أمريكا الشمالية |
67 |
C234 |
بترا مولر |
ألمانيا |
أوروبا |
51 |
C456 |
ماريا غونزاليس |
المكسيك |
أمريكا الشمالية |
26 |
اختيار عمود واحد باستخدام .loc
لاختيار الأعمدة، نحتاج إلى تحديد وسيط column_indexer
، الذي يأتي بعد وسيط row_indexer
. إذا أردنا فقط تحديد column_indexer
، نحتاج إلى وضع علامة على أننا نريد إرجاع جميع الصفوف وتصفية الأعمدة فقط. دعونا نرى كيف يمكننا فعل ذلك!
يمكن اختيار عمود واحد عن طريق تحديد column_indexer
مع علامة العمود المعني. لاسترجاع جميع الصفوف، نحتاج إلى تحديد row_indexer
مع نقطتين بسيطتين. نصل إلى بناء جملة يبدو كالتالي: df.loc[:, 'اسم العمود']
.
دعونا نعرض اسم
كل عميل:
df.loc[:, 'Name']
معرف العميل |
اسم |
C123 |
جون دو |
C234 |
بترا مولر |
C345 |
علي خان |
C456 |
ماريا غونزاليس |
C567 |
ديفيد لي |
اختيار عدة أعمدة باستخدام .loc
يشبه اختيار عدة صفوف، نحتاج إلى تمرير قائمة من تسميات الأعمدة إذا أردنا إرجاع عدة أعمدة من DataFrame التي لا تتبع بالضرورة بعضها البعض بالترتيب: df.loc[:, [col_label_1, 'col_label_2']]
.
افترض أننا أردنا إضافة جميع أعمار
العملاء إلى مخرجاتنا الأخيرة، سيكون الأمر على النحو التالي:
df.loc[:, ['Name', 'Age']]
معرّف العميل |
الاسم |
العمر |
C123 |
جون دو |
67 |
C234 |
بترا مولر |
51 |
C345 |
علي خان |
19 |
C456 |
ماريا غونزاليس |
26 |
C567 |
ديفيد لي |
40 |
تحديد شريحة من الأعمدة باستخدام .loc
استخدام نقطتين بين تسميات عمودين سيحدد جميع الأعمدة في النطاق بين العمودين المحددين. يشمل العمود النهائي، مما يعني أن العمود المسمى col_end
سيتم اختياره أيضًا في الصيغة القياسية، وهي كما يلي: df.loc[:, 'col_start':'col_end']
.
إذا كنا مهتمين بـ الاسم
، الدولة
، و المنطقة
لعملائنا، يمكن أن تكون سطر الشيفرة لدينا:
df.loc[:, 'Name':'Region']
معرف العميل |
الاسم |
الدولة |
المنطقة |
C123 |
جون دو |
الولايات المتحدة |
أمريكا الشمالية |
C234 |
بترا مولر |
ألمانيا |
أوروبا |
C345 |
علي خان |
باكستان |
آسيا |
C456 |
ماريا غونزاليس |
المكسيك |
أمريكا الشمالية |
C567 |
ديفيد لي |
الصين |
آسيا |
اختيار الصفوف والأعمدة معًا باستخدام .loc
من الممكن أيضًا تحديد كل من row_indexer
وcolumn_indexer
. يمكن استخدام ذلك لاسترجاع قطعة واحدة من المعلومات، مما يعني خلية واحدة من DataFrame. للقيام بذلك، نقوم بتحديد صف واحد وعمود واحد باستخدام الصيغة df.loc['row_label', 'column_name']
.
الحالة الأكثر فائدة هي إرجاع DataFrame فرعي يركز بالضبط على مجموعة الصفوف والأعمدة التي نهتم بها. من الممكن تحديد كل من الفهارس كقوائم باستخدام الأقواس المربعة، أو كشرائح باستخدام النقطتين، وحتى دمجها مع تعبير شرطي لاختيار الصف.
إليك مثال واحد على إرجاع Name
وCountry
وRegion
لكل عميل بعمر Age
يزيد عن 30:
df.loc[df['Age'] > 30, 'Name':'Region']
معرف العميل |
الاسم |
الدولة |
المنطقة |
C123 |
جون دو |
الولايات المتحدة |
أمريكا الشمالية |
C234 |
بترا مولر |
ألمانيا |
أوروبا |
C567 |
ديفيد لي |
الصين |
آسيا |
استخدام .iloc: الاختيار بواسطة موضع العدد
.iloc
يختار حسب الموضع بدلاً من التسمية. هذه هي الصيغة القياسية لاستخدام .iloc
: df.iloc[row_indexer, column_indexer]
. هناك أمران خاصان يجب الانتباه لهما:
- العد بدءًا من 0: الصف الأول والعمود لهما الفهرس 0، والثاني له الفهرس 1، وهكذا.
- حصريّة قيمة نهاية النطاق: عند استخدام شريحة، فإن الصف أو العمود المحدد خلف النقطتين لا يتم تضمينه في الاختيار.
اختيار صف واحد باستخدام .iloc
يمكن اختيار صف واحد باستخدام العدد الصحيح الذي يمثل رقم فهرس الصف كـ row_indexer
. لا نحتاج إلى علامات اقتباس لأننا ندخل رقمًا صحيحًا وليس سلسلة تسمية كما فعلنا مع .loc
. لإرجاع الصف الأول من DataFrame يسمى df
، أدخل df.iloc[0]
.
في مثال DataFrame الخاص بنا، هذه السطر من الشيفرة يعيد معلومات جون دو:
df.iloc[0]
C123 |
|
Name |
John Doe |
Country |
United States |
Region |
North America |
Age |
67 |
اختيار عدة صفوف باستخدام .iloc
يعمل اختيار عدة صفوف في .iloc
كما يفعل في .loc
– ندخل أرقام فهرس الصفوف في قائمة بأقواس مربعة. يبدو الصيغة بهذا الشكل: df.iloc[[0، 3، 4]]
.
يمكن رؤية الناتج المتوافق في جدول العملاء لدينا أدناه:
df.iloc[[0, 3, 4]]
Customer ID |
Name |
Country |
Region |
Age |
C123 |
John Doe |
الولايات المتحدة |
أمريكا الشمالية |
67 |
C456 |
ماريا غونزاليس |
المكسيك |
أمريكا الشمالية |
26 |
C567 |
ديفيد لي |
الصين |
آسيا |
40 |
تحديد شريحة من الصفوف باستخدام .iloc
لتحديد شريحة من الصفوف، نستخدم علامة الاقتباس بين رقمي فهرس الصفوف المحددين. الآن، علينا أن نولي اهتمامًا للحصرية المذكورة سابقًا.
يمكننا أن نأخذ السطر df.iloc[1:4]
كمثال لتوضيح هذا المفهوم. يعني الرقم المؤشري 1 الصف الثاني، لذا تبدأ شريحتنا من هناك. يمثل الرقم المؤشري 4 الصف الخامس – لكن نظرًا لأن .iloc
لا يشمل الاختيار الشريحة، سيتم إرجاع الصفوف الموجودة حتى قبل هذا الصف الأخير. لذلك، سيتم إرجاع الصف الثاني والثالث والرابع.
دعونا نثبت أن السطر يعمل كما يجب:
df.iloc[1:4]
معرف العميل |
الاسم |
الدولة |
المنطقة |
العمر |
C234 |
بيترا مولر |
ألمانيا |
أوروبا |
51 |
C345 |
علي خان |
باكستان |
آسيا |
19 |
C456 |
ماريا غونزاليس |
المكسيك |
أمريكا الشمالية |
26 |
اختيار عمود واحد باستخدام .iloc
تتبع منطق اختيار الأعمدة باستخدام .iloc
ما تعلمناه حتى الآن. دعنا نرى كيف يعمل مع الأعمدة الفردية، والأعمدة المتعددة وشرائح الأعمدة.
تمامًا كما هو الحال مع .loc
، من المهم تحديد row_indexer
قبل أن نتمكن من الانتقال إلى column_indexer
. لاسترداد قيم العمود الثالث من df
لكل صف، ندخل df.iloc[:, 2]
.
نظرًا لأن Region
هو العمود الثالث في إطار البيانات الخاص بنا، فسيتم استرجاعه نتيجة لهذا السطر من الكود:
df.iloc[:, 2]
معرف العميل |
المنطقة |
C123 |
أمريكا الشمالية |
C234 |
أوروبا |
C345 |
آسيا |
C456 |
أمريكا الشمالية |
C567 |
آسيا |
اختيار أعمدة متعددة باستخدام .iloc
لاختيار أعمدة متعددة ليست بالضرورة متتالية، يمكننا مرة أخرى إدخال قائمة تحتوي على أعداد صحيحة كـ column_indexer
. السطر df.iloc[:, [0, 3]]
يُرجع كلا من العمود الأول والرابع.
في حالتنا، المعلومات المعروضة هي الاسم
بالإضافة إلى العمر
لكل عميل:
df.iloc[:, [0, 3]]
رقم العميل |
الاسم |
العمر |
C123 |
جون دو |
67 |
C234 |
بيتر مولر |
51 |
C345 |
علي خان |
19 |
C456 |
ماريا غونزاليس |
26 |
C567 |
دايفيد لي |
40 |
اختيار شريحة من الأعمدة باستخدام .iloc
لتحديد الشريحة باستخدام .iloc
، تتبع منطق column_indexer
منطق row_indexer
. العمود الممثل بالعدد بعد الفاصلة لا يتم تضمينه في الناتج. لاسترداد العمود الثاني والثالث، يجب أن يكون شكل الكود كالتالي: df.iloc[:, 1:3]
.
يُعيد السطر أدناه جميع المعلومات الجغرافية التي لدينا حول عملائنا:
df.iloc[:, 1:3]
رقم العميل |
الدولة |
المنطقة |
C123 |
الولايات المتحدة |
أمريكا الشمالية |
C234 |
ألمانيا |
أوروبا |
C345 |
باكستان |
آسيا |
C456 |
المكسيك |
أمريكا الشمالية |
C567 |
الصين |
آسيا |
اختيار الصفوف والأعمدة معاً باستخدام .iloc
يمكننا تجميع ما تعلمناه عن .iloc
لدمج اختيار الصفوف والأعمدة. مرة أخرى، من الممكن إرجاع خلية واحدة أو إطار بيانات فرعي. لإرجاع الخلية الوحيدة عند تقاطع الصف 3 والعمود 4، ندخل df.iloc[2, 3]
.
تمامًا كما مع .loc
، يمكننا تحديد كلا المؤشرين كقوائم باستخدام الأقواس المربعة، أو كشرائح باستخدام النقطتين. إذا أردنا اختيار الصفوف باستخدام تعبيرات شرطية، فهذا ممكن تقنيًا مع .iloc
أيضًا، لكن لا يُوصى به. استخدام أسماء التسمية و.loc
عادة ما يكون أكثر بديهية وأقل عرضة للأخطاء.
هذا المثال الأخير يعرض البلد
، المنطقة
والعمر
للصف الأول والثاني والخامس في إطار بياناتنا:
df.iloc[[0,1,4], 1:4]
معرف العميل |
البلد |
المنطقة |
العمر |
C123 |
الولايات المتحدة |
شمال أمريكا |
67 |
C234 |
ألمانيا |
أوروبا |
51 |
C567 |
الصين |
آسيا |
40 |
.iloc مقابل .loc: متى يجب استخدام كل منهما
بشكل عام، هناك قاعدة بسيطة تعتمد على فهمك للبيانات:
- استخدم
.loc
عندما تعرف التسميات (الأسماء) للصفوف/الأعمدة. - استخدم
.iloc
عندما تعرف مواقع الأعداد الصحيحة للصفوف/الأعمدة.
توجد بعض السيناريوهات التي تفضل إما .loc
أو .iloc
بناءً على طبيعتها. على سبيل المثال، يكون التكرار عبر الصفوف أو الأعمدة أسهل وأكثر بديهية باستخدام الأعداد الصحيحة بدلاً من العلامات. كما ذكرنا بالفعل، فإن تصفية الصفوف بناءً على شروط قيم الأعمدة أقل عرضة للأخطاء باستخدام أسماء الأعمدة.
السيناريوهات التي تفضل .loc |
السيناريوهات التي تفضل .iloc |
يحتوي DataFrame الخاص بك على أسماء فهرس/أعمدة ذات معنى. |
أنت تقوم بالتكرار عبر الصفوف/الأعمدة حسب موقعها. |
تحتاج إلى تصفية بناءً على شروط تتعلق بقيم الأعمدة. |
أسماء الفهرس/الأعمدة ليست ذات صلة بمهمتك. |
خطأ في المفتاح، خطأ في الاسم، وخطأ في الفهرس مع .loc و .iloc
لنلقِ نظرة على المشاكل المحتملة. أحد الأخطاء الشائعة عند استخدام .loc
هو مواجهة KeyError
. يحدث هذا الخطأ عندما نحاول الوصول إلى تسمية صف أو عمود غير موجودة داخل إطار البيانات الخاص بنا. لتجنب ذلك، يجب علينا دائمًا التأكد من أن التسميات التي نستخدمها دقيقة وأنها تتطابق مع التسميات الموجودة في إطار البيانات الخاص بك وأن نتحقق مرة أخرى من الأخطاء المطبعية.
بالإضافة إلى ذلك، من المهم دائمًا استخدام علامات الاقتباس للتسميات المحددة باستخدام .loc
. نسيانها سيؤدي إلى إرجاع NameError
.
يمكن أن يحدث خطأ IndexError
عند استخدام .iloc
إذا حددنا موضعًا عدديًا خارج النطاق الصالح لمؤشرات DataFrame لدينا. يحدث هذا عندما لا يوجد الفهرس الذي تحاول الوصول إليه، إما لأنه يتجاوز عدد الصفوف أو الأعمدة في DataFrame الخاص بك أو لأنه قيمة سالبة. لتجنب هذا الخطأ، تحقق من أبعاد DataFrame الخاص بك واستخدم قيم فهرس مناسبة ضمن النطاق الصالح.
خاتمة
آمل أن تكون هذه المدونة قد كانت مفيدة وأن يكون الفارق بين .loc
و .iloc
واضحًا الآن. للتعرف على المزيد، إليك بعض الخطوات الجيدة التالية: