أطلق العنان للإمكانات الكاملة لـ NumPy باستخدام تقنيات فهرسة المصفوفات المتقدمة. تعلم الفهرسة المنطقية والفهرسة الفاخرة والتقطيع لاختيار البيانات بكفاءة.
فهرسة مصفوفات NumPy: إتقان تقنيات التحديد المتقدمة
تُعد NumPy، حجر الزاوية في الحوسبة العلمية في بايثون، أدوات قوية للتعامل مع المصفوفات والمصفوفات الكبيرة ومتعددة الأبعاد. بينما تُعد الفهرسة والتقطيع الأساسيان أمرًا جوهريًا، فإن إتقان NumPy حقًا يتضمن التعمق في تقنيات التحديد الأكثر تقدمًا. تسمح هذه الأساليب بمعالجة البيانات المعقدة، مما يمكّن المستخدمين من استخراج المعلومات التي يحتاجونها بدقة وكفاءة ملحوظة. ستُرشدك هذه المقالة خلال تعقيدات الفهرسة المنطقية والفهرسة الفاخرة، وستقدم أمثلة عملية ورؤى لجمهور عالمي.
فهم الأساس: الفهرسة الأساسية والتقطيع
قبل أن نغامر بالدخول إلى المناطق المتقدمة، يُعد تلخيص موجز للفهرسة والتقطيع الأساسيين مفيدًا. بالنسبة لمصفوفة أحادية البعد (1D)، تكون الفهرسة مباشرة: arr[i] تسترجع العنصر في الفهرس i. يستخدم التقطيع بناء الجملة arr[start:stop:step] لتحديد نطاق من العناصر.
بالنسبة للمصفوفات ثنائية الأبعاد (2D)، تمتد الفهرسة لتشمل تحديد الصفوف والأعمدة. على سبيل المثال، arr[row, column] يصل إلى عنصر معين. يمكن تطبيق التقطيع بشكل مستقل على الصفوف والأعمدة: arr[row_slice, column_slice].
لنأخذ مصفوفة ثنائية الأبعاد بسيطة:
import numpy as np
arr_2d = np.array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
# Accessing an element
print(arr_2d[1, 2]) # Output: 6
# Slicing rows and columns
print(arr_2d[0:2, 1:3])
# Output:
# [[2 3]
# [5 6]]
على الرغم من فعاليتها، يمكن أن تصبح هذه الأساليب مرهقة عند التعامل مع معايير تحديد معقدة. وهنا تبرز تقنيات الفهرسة المتقدمة.
الفهرسة المنطقية: تحديد البيانات بناءً على الشروط
تسمح لك الفهرسة المنطقية، التي غالبًا ما يُشار إليها بالاختيار الشرطي، بتحديد عناصر من مصفوفة بناءً على شرط منطقي. تُعد هذه تقنية قوية للغاية لتصفية البيانات. تُنشئ مصفوفة منطقية بنفس شكل المصفوفة الأصلية، حيث تشير True إلى أنه يجب تحديد العنصر المقابل، وتشير False إلى الاستبعاد.
كيف تعمل
تتضمن العملية عادةً إجراء عملية مقارنة على المصفوفة. تُرجع هذه العملية مصفوفة منطقية. ثم تستخدم هذه المصفوفة المنطقية لفهرسة المصفوفة الأصلية.
المثال 1: تحديد العناصر الأكبر من قيمة
لنفترض أن لديك مجموعة بيانات لدرجات الحرارة العالمية وتريد تحديد جميع الأيام التي تجاوزت فيها درجة الحرارة عتبة معينة.
# Assume a 1D array of temperatures from various cities worldwide
temperatures = np.array([25.5, 31.2, 18.9, 28.7, 22.1, 35.0, 15.6])
# Set a threshold
threshold = 28.0
# Create a boolean mask
high_temperatures_mask = temperatures > threshold
print(high_temperatures_mask)
# Output: [False True False True False True False]
# Use the mask to select elements
hot_days = temperatures[high_temperatures_mask]
print(hot_days)
# Output: [31.2 28.7 35. ]
تحدد هذه الطريقة بوضوح جميع درجات الحرارة التي تزيد عن 28.0 درجة. الناتج هو مصفوفة أحادية البعد جديدة تحتوي فقط على القيم التي استوفت الشرط.
المثال 2: العمل مع المصفوفات ثنائية الأبعاد
يمكن تطبيق الفهرسة المنطقية أيضًا على المصفوفات متعددة الأبعاد. عند استخدامها مع مصفوفة ثنائية الأبعاد، ستُرجع القناع المنطقي بنفس الشكل مصفوفة أحادية البعد تحتوي على جميع العناصر التي يكون القناع لها True.
# A 2D array representing sales figures for different products across regions
sales_data = np.array([[150, 200, 120],
[300, 180, 250],
[90, 220, 160]])
# Identify sales figures above a certain target
target_sales = 200
# Create a boolean mask
successful_sales_mask = sales_data >= target_sales
print(successful_sales_mask)
# Output:
# [[False True False]
# [ True False True]
# [False True False]]
# Select the corresponding sales figures
selected_sales = sales_data[successful_sales_mask]
print(selected_sales)
# Output: [200 300 250 220]
تُرجع هذه الطريقة مصفوفة أحادية البعد لجميع أرقام المبيعات التي حققت الهدف أو تجاوزته. إنها طريقة قوية لتصفية البيانات متعددة الأبعاد دون الحاجة إلى حلقات صريحة.
الفهرسة المنطقية بشروط متعددة
يمكنك دمج شروط منطقية متعددة باستخدام عوامل التشغيل المنطقية:
&: (AND) المنطقي على مستوى العنصر|: (OR) المنطقي على مستوى العنصر~: (NOT) المنطقي على مستوى العنصر
ملاحظة هامة: عند دمج الشروط، يجب أن يكون كل شرط فردي محاطًا بقوسين بسبب أسبقية عوامل التشغيل في بايثون.
# Select sales figures that are between 150 and 250 (inclusive)
condition_low = sales_data >= 150
condition_high = sales_data <= 250
between_150_and_250 = sales_data[condition_low & condition_high]
print(between_150_and_250)
# Output: [150 200 180 250 220 160]
يوضح هذا كيفية استخراج البيانات التي تقع ضمن نطاق معين، وهي مهمة شائعة في تحليل البيانات.
الفهرسة الفاخرة: تحديد العناصر باستخدام مصفوفات الأعداد الصحيحة
الفهرسة الفاخرة هي تقنية اختيار متقدمة أخرى تسمح لك بتحديد العناصر باستخدام مصفوفات الأعداد الصحيحة. تختلف هذه عن التقطيع، الذي يحدد كتلًا متجاورة من البيانات. تمكنك الفهرسة الفاخرة من اختيار عناصر عشوائية من مصفوفة بناءً على فهارسها.
كيف تعمل
توفر مصفوفة من الفهارس إلى عامل الفهرسة. ثم تُرجع NumPy مصفوفة جديدة حيث يتم ترتيب العناصر وفقًا للفهارس المقدمة.
المثال 1: تحديد عناصر محددة في مصفوفة أحادية البعد
تخيل أن لديك قائمة بمعرفات المستخدمين وتريد استرداد البيانات للمستخدمين المحددين فقط.
# A list of sample user IDs
user_ids = np.array([101, 105, 110, 102, 115, 108])
# Indices of the users we are interested in
selected_indices = np.array([0, 3, 5]) # Corresponds to user IDs at index 0, 3, and 5
# Select the data for these users
selected_users = user_ids[selected_indices]
print(selected_users)
# Output: [101 102 108]
تُرجع هذه الطريقة مصفوفة جديدة تحتوي فقط على user_ids عند الفهارس المحددة.
المثال 2: الفهرسة الفاخرة مع المصفوفات ثنائية الأبعاد
تصبح الفهرسة الفاخرة قوية بشكل خاص مع المصفوفات متعددة الأبعاد. عند استخدام مصفوفات الأعداد الصحيحة لفهرسة مصفوفة ثنائية الأبعاد، يمكنك تحديد صفوف أو أعمدة محددة، أو حتى عناصر فردية بطريقة غير متجاورة.
هناك طريقتان أساسيتان لاستخدام الفهرسة الفاخرة مع المصفوفات ثنائية الأبعاد:
- تحديد الصفوف: توفير مصفوفة أحادية البعد لفهارس الصفوف.
- تحديد عناصر محددة (أزواج الصفوف والأعمدة): توفير مصفوفتين أحاديتي البعد من الفهارس - واحدة للصفوف وواحدة للأعمدة. يجب أن تكون هذه المصفوفات بنفس الطول، ويحدد العنصر الـ i من مصفوفة فهارس الصفوف والعنصر الـ i من مصفوفة فهارس الأعمدة عنصرًا فريدًا ليتم تحديده.
تحديد صفوف معينة
لنأخذ مجموعة بيانات لأسعار الأسهم لشركات مختلفة على مدار عدة أيام. نريد استرداد البيانات لشركات معينة.
# Stock prices for 3 companies over 4 days
# Rows represent days, columns represent companies
stock_prices = np.array([[100, 150, 200],
[105, 152, 205],
[110, 155, 210],
[115, 160, 215]])
# Indices of the companies we want to examine (e.g., company at index 0 and company at index 2)
company_indices = np.array([0, 2])
# Select the data for these companies across all days
selected_companies_data = stock_prices[:, company_indices]
print(selected_companies_data)
# Output:
# [[100 200]
# [105 205]
# [110 210]
# [115 215]]
هنا، تحدد : جميع الصفوف، وتحدد company_indices أعمدة محددة. الناتج هو مصفوفة ثنائية الأبعاد جديدة حيث يتوافق كل عمود مع الشركات المحددة.
تحديد عناصر محددة باستخدام أزواج الصفوف والأعمدة
هنا تُقدم الفهرسة الفاخرة أكبر قدر من المرونة. يمكنك تحديد عناصر عشوائية عن طريق تحديد فهارس الصفوف والأعمدة الخاصة بها في نفس الوقت.
# A grid representing population density across different zones and sectors
population_density = np.array([[1000, 1200, 800, 1500],
[900, 1100, 750, 1400],
[1300, 1400, 950, 1600],
[850, 1050, 700, 1350]])
# We want to check the density at specific zone-sector combinations.
# Let's say we are interested in:
# - Zone 0, Sector 1 (row 0, col 1)
# - Zone 2, Sector 0 (row 2, col 0)
# - Zone 1, Sector 3 (row 1, col 3)
# - Zone 3, Sector 2 (row 3, col 2)
row_indices = np.array([0, 2, 1, 3])
column_indices = np.array([1, 0, 3, 2])
# Select the population densities at these specific locations
specific_locations_density = population_density[row_indices, column_indices]
print(specific_locations_density)
# Output: [1200 1300 1400 700]
الناتج هو مصفوفة أحادية البعد تحتوي على كثافات السكان عند الإحداثيات الدقيقة المحددة بواسطة أزواج الفهارس.
فكرة رئيسية: يتم تحديد شكل المصفوفة الناتجة من خلال شكل مصفوفات الفهرس. إذا كانت كلتا مصفوفتي الفهرس أحادية البعد ولهما نفس الطول N، فسيكون الناتج مصفوفة أحادية البعد بطول N. إذا كانت إحدى مصفوفات الفهرس متعددة الأبعاد، فستورث المصفوفة الناتجة هذا الشكل.
الفهرسة الفاخرة والبث (Broadcasting)
عند استخدام الفهرسة الفاخرة مع مصفوفات فهارس متعددة لها أشكال مختلفة، تدخل قواعد بث NumPy حيز التنفيذ. على سبيل المثال، إذا قمت بفهرسة مصفوفة ثنائية الأبعاد باستخدام مصفوفة أحادية البعد للصفوف ورقم صحيح واحد للأعمدة، فسيقوم البث بتوسيع فهرس العمود الفردي هذا ليتطابق مع عدد الصفوف.
# Let's select all elements from the first two rows, but only from the third column
indices_rows = np.array([0, 1]) # Indices of rows
index_col = 2 # Index of the column
selected_subset = population_density[indices_rows, index_col]
print(selected_subset)
# Output: [800 750]
في هذه الحالة، يتم بث index_col (وهو 2) لمطابقة شكل indices_rows (وهو (2,))، مما يؤدي فعاليًا إلى إنشاء أزواج الفهارس (0, 2) و (1, 2).
الجمع بين الفهرسة المنطقية والفهرسة الفاخرة
يمكنك أيضًا دمج الفهرسة المنطقية والفهرسة الفاخرة لإنشاء أنماط تحديد أكثر تعقيدًا. على سبيل المثال، قد تقوم أولاً بتصفية الصفوف بناءً على شرط ثم تستخدم الفهرسة الفاخرة لتحديد أعمدة محددة من تلك الصفوف المفلترة.
لنعد إلى مثال sales_data:
# sales_data = np.array([[150, 200, 120],
# [300, 180, 250],
# [90, 220, 160]])
# Let's say we only want to consider rows where at least one sale figure is above 200
# Create a boolean mask for rows
# We check if any element in a row is greater than 200
row_mask = np.any(sales_data > 200, axis=1)
print(row_mask)
# Output: [False True True]
# Apply this row mask to select relevant rows
filtered_rows = sales_data[row_mask]
print(filtered_rows)
# Output:
# [[300 180 250]
# [ 90 220 160]]
# Now, from these filtered rows, let's use fancy indexing to select specific columns.
# Suppose we want the first and third columns from these filtered rows.
row_indices_for_fancy = np.array([0, 1]) # Indices within the filtered_rows array
column_indices_for_fancy = np.array([0, 2]) # Indices of columns we want
final_selection = filtered_rows[row_indices_for_fancy, column_indices_for_fancy]
print(final_selection)
# Output: [300 160]
يوضح هذا المثال سيناريو حيث تقوم أولاً بتصفية بياناتك بناءً على شرط عام (صفوف ذات مبيعات عالية) ثم تستخرج نقاط بيانات محددة بشكل انتقائي من تلك الصفوف المفلترة.
تطبيقات عملية ومنظورات عالمية
هذه التقنيات المتقدمة للفهرسة ليست مجرد مفاهيم نظرية؛ إنها أدوات لا غنى عنها في تطبيقات علم البيانات الواقعية في جميع أنحاء العالم:
- التحليل المالي: تحديد أسعار الأسهم لشركات معينة في تواريخ محددة، أو تحديد الصفقات التي استوفت عتبات ربحية معينة.
- علم المناخ: تصفية بيانات درجة الحرارة أو هطول الأمطار لمناطق جغرافية أو فترات زمنية محددة بناءً على معايير محددة. على سبيل المثال، تحديد المناطق المعرضة للجفاف (مثل أجزاء من أستراليا، منطقة الساحل في إفريقيا) عن طريق اختيار البيانات الأقل من مستوى معين لهطول الأمطار.
- التجارة الإلكترونية: تجزئة بيانات العملاء لتحديد العملاء ذوي القيمة العالية أو المنتجات ذات مقاييس مبيعات محددة عبر أسواق مختلفة (مثل أوروبا، آسيا، أمريكا الشمالية).
- الرعاية الصحية: تحليل بيانات المرضى لاختيار سجلات الأفراد الذين يعانون من حالات محددة أو تواريخ علاج عبر مجموعات سكانية متنوعة.
- التعلم الآلي: إعداد مجموعات البيانات عن طريق اختيار الميزات أو العينات بناءً على معايير معقدة، أو استخراج معاملات النموذج لمعلمات محددة.
إن القدرة على اختيار البيانات بدقة وكفاءة أمر بالغ الأهمية لبناء نماذج دقيقة، واستخلاص رؤى ذات معنى، واتخاذ قرارات مستنيرة، بغض النظر عن الموقع الجغرافي أو الصناعة.
اعتبارات الأداء
تُعد الفهرسة المتقدمة في NumPy محسّنة للغاية. غالبًا ما يتم تحويل العمليات التي تتطلب حلقات بايثون صريحة إلى عمليات متجهة بواسطة NumPy، مما يؤدي إلى مكاسب كبيرة في الأداء. ومع ذلك، من المهم أن تكون على دراية ببعض الفروق الدقيقة:
- الفهرسة المنطقية تُرجع عمومًا مصفوفة أحادية البعد للعناصر المحددة. إذا كنت بحاجة إلى الاحتفاظ بالشكل الأصلي لعمليات معينة، فقد تحتاج إلى إعادة التشكيل أو استخدام تقنيات أخرى.
- الفهرسة الفاخرة تُرجع نسخة من البيانات. إذا كانت مصفوفات الفهرس أعدادًا صحيحة، فإن النتيجة تكون نسخة. إذا كانت مصفوفات الفهرس منطقية، فإن النتيجة تكون أيضًا نسخة. هذا يعني أن التغييرات في المصفوفة المُرجعة لا تؤثر على المصفوفة الأصلية.
- بالنسبة للمصفوفات الكبيرة جدًا ومخططات الفهرسة المعقدة، يمكن أن يصبح استخدام الذاكرة عاملاً. تُنشئ عمليات NumPy مصفوفات وسيطة، والتي تستهلك الذاكرة.
عندما يكون الأداء حاسمًا، خاصة في التطبيقات الحساسة للوقت أو عند العمل مع مجموعات بيانات ضخمة، فإن تحليل كودك وفهم عمليات NumPy الأساسية يمكن أن يساعدك على تحسين الأداء بشكل أكبر. قد يتضمن ذلك الاختيار بين الفهرسة المنطقية والفهرسة الفاخرة، أو إعادة هيكلة بياناتك.
أفضل الممارسات للفهرسة المتقدمة
للاستفادة الفعالة من قدرات الفهرسة المتقدمة في NumPy:
- افهم بياناتك: حدد بوضوح معايير الاختيار قبل كتابة الكود.
- استخدم أسماء متغيرات ذات معنى: سمِّ أقنعةك المنطقية ومصفوفات الفهرس بأسماء وصفية (على سبيل المثال،
high_value_customers_mask،target_product_indices). - أعط الأولوية للقراءة: بينما الكود المختصر جيد، أعط الأولوية للكود السهل الفهم للآخرين (ولنفسك في المستقبل). استخدم الأقواس بشكل مناسب للشروط المنطقية المدمجة.
- اختبر بشكل تدريجي: ابنِ عمليات الفهرسة المعقدة خطوة بخطوة، مع التحقق من الناتج في كل مرحلة.
- استفد من دوال NumPy: استخدم دوال مثل
np.where()للاختيار الشرطي الذي قد يُرجع فهارس أو قيمًا، أوnp.ix_()لإنشاء شبكة كاملة من مصفوفات الفهرس، وهو ما يمكن أن يكون مفيدًا في سيناريوهات محددة. - كن على دراية بالنسخ مقابل العروض (Copies vs. Views): تذكر أن الفهرسة الفاخرة والفهرسة المنطقية تُرجعان عادةً نسخًا، وليس عروضًا للبيانات الأصلية.
الخاتمة
تُعد تقنيات فهرسة المصفوفات المتقدمة في NumPy، وهي الفهرسة المنطقية والفهرسة الفاخرة، أساسية لأداء اختيار البيانات ومعالجتها بشكل متطور في بايثون. إنها تمكن علماء البيانات والمحللين والباحثين في جميع أنحاء العالم من استخراج البيانات التي يحتاجونها بدقة، مما يتيح رؤى أعمق وتحليلات أكثر قوة. من خلال إتقان هذه التقنيات، يمكنك إطلاق العنان للقوة الكاملة لـ NumPy لمشاريعك القائمة على البيانات، والمساهمة في التطورات في مجالات تتراوح من التمويل العالمي وبحوث المناخ إلى الطب الشخصي والذكاء الاصطناعي. استمر في الاستكشاف والتجربة ودمج طرق التحديد القوية هذه في سير عملك مع NumPy.