You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

345 lines
24 KiB

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "1b560955ff39a2bcf2a049fce474a951",
"translation_date": "2025-09-06T06:23:58+00:00",
"source_file": "2-Working-With-Data/08-data-preparation/README.md",
"language_code": "ar"
}
-->
# العمل مع البيانات: إعداد البيانات
|![ رسم توضيحي بواسطة [(@sketchthedocs)](https://sketchthedocs.dev) ](../../sketchnotes/08-DataPreparation.png)|
|:---:|
|إعداد البيانات - _رسم توضيحي بواسطة [@nitya](https://twitter.com/nitya)_ |
## [اختبار ما قبل المحاضرة](https://ff-quizzes.netlify.app/en/ds/quiz/14)
اعتمادًا على مصدرها، قد تحتوي البيانات الخام على بعض التناقضات التي تسبب تحديات في التحليل والنمذجة. بمعنى آخر، يمكن تصنيف هذه البيانات على أنها "غير نظيفة" وستحتاج إلى تنظيفها. تركز هذه الدرس على تقنيات تنظيف وتحويل البيانات للتعامل مع تحديات البيانات المفقودة أو غير الدقيقة أو غير المكتملة. المواضيع التي يتم تناولها في هذا الدرس ستستخدم مكتبة Python وPandas وسيتم [عرضها في الدفتر](../../../../2-Working-With-Data/08-data-preparation/notebook.ipynb) داخل هذا الدليل.
## أهمية تنظيف البيانات
- **سهولة الاستخدام وإعادة الاستخدام**: عندما تكون البيانات منظمة ومُطَبَّعة بشكل صحيح، يصبح من السهل البحث عنها واستخدامها ومشاركتها مع الآخرين.
- **الاتساق**: غالبًا ما يتطلب علم البيانات العمل مع أكثر من مجموعة بيانات، حيث يجب دمج مجموعات البيانات من مصادر مختلفة معًا. ضمان أن كل مجموعة بيانات فردية لديها توحيد مشترك سيضمن أن البيانات تظل مفيدة عند دمجها في مجموعة بيانات واحدة.
- **دقة النماذج**: تحسين دقة النماذج يعتمد على البيانات النظيفة.
## أهداف واستراتيجيات التنظيف الشائعة
- **استكشاف مجموعة البيانات**: يمكن أن يساعد استكشاف البيانات، الذي يتم تناوله في [درس لاحق](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/4-Data-Science-Lifecycle/15-analyzing)، في اكتشاف البيانات التي تحتاج إلى تنظيف. يمكن أن يوفر استكشاف القيم داخل مجموعة البيانات فكرة عن شكل باقي البيانات أو المشاكل التي يمكن حلها. يشمل الاستكشاف الاستعلامات الأساسية، التصورات، وأخذ العينات.
- **التنسيق**: اعتمادًا على المصدر، قد تحتوي البيانات على تناقضات في كيفية تقديمها. يمكن أن يسبب هذا مشاكل في البحث عن القيم وتمثيلها، حيث تظهر داخل مجموعة البيانات ولكنها لا تُعرض بشكل صحيح في التصورات أو نتائج الاستعلام. تشمل مشاكل التنسيق الشائعة معالجة المسافات البيضاء، التواريخ، وأنواع البيانات. عادةً ما يكون حل مشاكل التنسيق مسؤولية الأشخاص الذين يستخدمون البيانات. على سبيل المثال، تختلف المعايير حول كيفية تقديم التواريخ والأرقام حسب البلد.
- **التكرارات**: يمكن أن تؤدي البيانات التي تحتوي على أكثر من تكرار إلى نتائج غير دقيقة وعادةً ما يجب إزالتها. يحدث هذا بشكل شائع عند دمج مجموعتين أو أكثر من البيانات معًا. ومع ذلك، هناك حالات قد تحتوي فيها التكرارات في مجموعات البيانات المدمجة على معلومات إضافية وقد تحتاج إلى الاحتفاظ بها.
- **البيانات المفقودة**: يمكن أن تسبب البيانات المفقودة نتائج غير دقيقة أو ضعيفة أو منحازة. يمكن حل هذه المشكلة أحيانًا عن طريق "إعادة تحميل" البيانات، أو ملء القيم المفقودة باستخدام الحسابات والرموز مثل Python، أو ببساطة إزالة القيمة والبيانات المرتبطة بها. هناك أسباب عديدة لفقدان البيانات، والإجراءات المتخذة لحل هذه القيم المفقودة تعتمد على كيفية ولماذا فقدت البيانات في المقام الأول.
## استكشاف معلومات DataFrame
> **هدف التعلم:** بنهاية هذا القسم، يجب أن تكون مرتاحًا في العثور على معلومات عامة حول البيانات المخزنة في DataFrames في pandas.
بمجرد تحميل البيانات في pandas، من المرجح أن تكون في DataFrame (راجع [الدرس السابق](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python#dataframe) للحصول على نظرة عامة مفصلة). ومع ذلك، إذا كانت مجموعة البيانات في DataFrame تحتوي على 60,000 صف و400 عمود، كيف يمكنك البدء في فهم ما تعمل معه؟ لحسن الحظ، توفر [pandas](https://pandas.pydata.org/) أدوات مريحة للنظر بسرعة في المعلومات العامة حول DataFrame بالإضافة إلى الصفوف الأولى والأخيرة.
لاستكشاف هذه الوظائف، سنقوم باستيراد مكتبة Python scikit-learn واستخدام مجموعة بيانات شهيرة: **مجموعة بيانات Iris**.
```python
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])
```
| |طول السبل (سم)|عرض السبل (سم)|طول البتلة (سم)|عرض البتلة (سم)|
|----------------------------------------|--------------|--------------|--------------|--------------|
|0 |5.1 |3.5 |1.4 |0.2 |
|1 |4.9 |3.0 |1.4 |0.2 |
|2 |4.7 |3.2 |1.3 |0.2 |
|3 |4.6 |3.1 |1.5 |0.2 |
|4 |5.0 |3.6 |1.4 |0.2 |
- **DataFrame.info**: للبدء، يتم استخدام طريقة `info()` لطباعة ملخص للمحتوى الموجود في `DataFrame`. دعونا نلقي نظرة على هذه المجموعة من البيانات لنرى ما لدينا:
```python
iris_df.info()
```
```
RangeIndex: 150 entries, 0 to 149
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal length (cm) 150 non-null float64
1 sepal width (cm) 150 non-null float64
2 petal length (cm) 150 non-null float64
3 petal width (cm) 150 non-null float64
dtypes: float64(4)
memory usage: 4.8 KB
```
من هذا، نعلم أن مجموعة بيانات *Iris* تحتوي على 150 إدخالًا في أربعة أعمدة بدون أي إدخالات فارغة. يتم تخزين جميع البيانات كأرقام عائمة 64-بت.
- **DataFrame.head()**: بعد ذلك، للتحقق من المحتوى الفعلي لـ `DataFrame`، نستخدم طريقة `head()`. دعونا نرى الصفوف الأولى من `iris_df`:
```python
iris_df.head()
```
```
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
```
- **DataFrame.tail()**: على العكس، للتحقق من الصفوف الأخيرة من `DataFrame`، نستخدم طريقة `tail()`:
```python
iris_df.tail()
```
```
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
145 6.7 3.0 5.2 2.3
146 6.3 2.5 5.0 1.9
147 6.5 3.0 5.2 2.0
148 6.2 3.4 5.4 2.3
149 5.9 3.0 5.1 1.8
```
> **الخلاصة:** حتى بمجرد النظر إلى البيانات الوصفية حول المعلومات في DataFrame أو القيم الأولى والأخيرة، يمكنك الحصول على فكرة فورية عن الحجم والشكل والمحتوى للبيانات التي تتعامل معها.
## التعامل مع البيانات المفقودة
> **هدف التعلم:** بنهاية هذا القسم، يجب أن تعرف كيفية استبدال أو إزالة القيم الفارغة من DataFrames.
غالبًا ما تحتوي مجموعات البيانات التي ترغب في استخدامها (أو تضطر إلى استخدامها) على قيم مفقودة. كيفية التعامل مع البيانات المفقودة تحمل معها توازنات دقيقة يمكن أن تؤثر على التحليل النهائي والنتائج الواقعية.
تتعامل pandas مع القيم المفقودة بطريقتين. الأولى التي رأيتها من قبل في الأقسام السابقة: `NaN`، أو ليس رقمًا. هذه في الواقع قيمة خاصة وهي جزء من مواصفات IEEE للأرقام العائمة وتستخدم فقط للإشارة إلى القيم العائمة المفقودة.
بالنسبة للقيم المفقودة بخلاف الأرقام العائمة، تستخدم pandas كائن Python `None`. على الرغم من أنه قد يبدو مربكًا أنك ستواجه نوعين مختلفين من القيم التي تقول نفس الشيء تقريبًا، إلا أن هناك أسبابًا برمجية سليمة لهذا الاختيار التصميمي، وفي الممارسة العملية، يتيح هذا النهج لـ pandas تقديم حل وسط جيد لمعظم الحالات. ومع ذلك، فإن كلا من `None` و`NaN` يحملان قيودًا يجب أن تكون على دراية بها فيما يتعلق بكيفية استخدامهما.
اطلع على المزيد حول `NaN` و`None` من [الدفتر](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/4-Data-Science-Lifecycle/15-analyzing/notebook.ipynb)!
- **اكتشاف القيم الفارغة**: في `pandas`، تعتبر طريقتا `isnull()` و`notnull()` الطرق الأساسية لاكتشاف البيانات الفارغة. كلاهما يعيد أقنعة منطقية فوق بياناتك. سنستخدم `numpy` للقيم `NaN`:
```python
import numpy as np
example1 = pd.Series([0, np.nan, '', None])
example1.isnull()
```
```
0 False
1 True
2 False
3 True
dtype: bool
```
انظر عن كثب إلى الإخراج. هل أي منه يفاجئك؟ بينما يعتبر `0` فارغًا حسابيًا، إلا أنه لا يزال عددًا صحيحًا صالحًا وتتعامل pandas معه على هذا النحو. أما `''` فهو أكثر دقة. على الرغم من أننا استخدمناه في القسم الأول لتمثيل قيمة سلسلة فارغة، إلا أنه لا يزال كائن سلسلة وليس تمثيلًا للفارغ كما تعتبره pandas.
الآن، دعونا نعكس هذا ونستخدم هذه الطرق بطريقة أكثر شبهًا بالطريقة التي ستستخدمها في الممارسة. يمكنك استخدام الأقنعة المنطقية مباشرة كمؤشر ``Series`` أو ``DataFrame``، وهو أمر مفيد عند محاولة العمل مع القيم الفارغة (أو الموجودة) المعزولة.
> **الخلاصة**: تنتج طريقتا `isnull()` و`notnull()` نتائج مشابهة عند استخدامهما في `DataFrame`s: تظهر النتائج وفهرس تلك النتائج، مما سيساعدك بشكل كبير أثناء التعامل مع بياناتك.
- **إزالة القيم الفارغة**: إلى جانب تحديد القيم المفقودة، توفر pandas وسيلة مريحة لإزالة القيم الفارغة من `Series` و`DataFrame`s. (خصوصًا في مجموعات البيانات الكبيرة، غالبًا ما يكون من الأفضل ببساطة إزالة القيم المفقودة [NA] من تحليلك بدلاً من التعامل معها بطرق أخرى.) لرؤية هذا عمليًا، دعونا نعود إلى `example1`:
```python
example1 = example1.dropna()
example1
```
```
0 0
2
dtype: object
```
لاحظ أن هذا يجب أن يبدو مثل الإخراج الخاص بك من `example3[example3.notnull()]`. الفرق هنا هو أنه بدلاً من مجرد الفهرسة على القيم المقنعة، قامت `dropna` بإزالة تلك القيم المفقودة من `Series` `example1`.
نظرًا لأن `DataFrame`s لها بعدان، فإنها توفر المزيد من الخيارات لإزالة البيانات.
```python
example2 = pd.DataFrame([[1, np.nan, 7],
[2, 5, 8],
[np.nan, 6, 9]])
example2
```
| | 0 | 1 | 2 |
|------|---|---|---|
|0 |1.0|NaN|7 |
|1 |2.0|5.0|8 |
|2 |NaN|6.0|9 |
(هل لاحظت أن pandas قامت بترقية اثنين من الأعمدة إلى أرقام عائمة لاستيعاب `NaN`s؟)
لا يمكنك إزالة قيمة واحدة من `DataFrame`، لذا عليك إزالة صفوف أو أعمدة كاملة. اعتمادًا على ما تقوم به، قد ترغب في القيام بأحدهما أو الآخر، لذا توفر pandas خيارات لكليهما. نظرًا لأن الأعمدة تمثل عادةً المتغيرات والصفوف تمثل الملاحظات في علم البيانات، فمن المرجح أن تقوم بإزالة صفوف البيانات؛ الإعداد الافتراضي لـ `dropna()` هو إزالة جميع الصفوف التي تحتوي على أي قيم فارغة:
```python
example2.dropna()
```
```
0 1 2
1 2.0 5.0 8
```
إذا لزم الأمر، يمكنك إزالة قيم NA من الأعمدة. استخدم `axis=1` للقيام بذلك:
```python
example2.dropna(axis='columns')
```
```
2
0 7
1 8
2 9
```
لاحظ أن هذا يمكن أن يؤدي إلى إزالة الكثير من البيانات التي قد ترغب في الاحتفاظ بها، خصوصًا في مجموعات البيانات الصغيرة. ماذا لو كنت تريد فقط إزالة الصفوف أو الأعمدة التي تحتوي على عدة أو حتى جميع القيم الفارغة؟ يمكنك تحديد تلك الإعدادات في `dropna` باستخدام معلمات `how` و`thresh`.
بشكل افتراضي، `how='any'` (إذا كنت ترغب في التحقق بنفسك أو رؤية المعلمات الأخرى التي تحتوي عليها الطريقة، قم بتشغيل `example4.dropna?` في خلية كود). يمكنك بدلاً من ذلك تحديد `how='all'` لإزالة الصفوف أو الأعمدة التي تحتوي على جميع القيم الفارغة فقط. دعونا نوسع مثالنا `DataFrame` لرؤية هذا عمليًا.
```python
example2[3] = np.nan
example2
```
| |0 |1 |2 |3 |
|------|---|---|---|---|
|0 |1.0|NaN|7 |NaN|
|1 |2.0|5.0|8 |NaN|
|2 |NaN|6.0|9 |NaN|
معلمة `thresh` تمنحك تحكمًا أكثر دقة: تحدد عدد القيم *غير الفارغة* التي يحتاجها الصف أو العمود ليتم الاحتفاظ به:
```python
example2.dropna(axis='rows', thresh=3)
```
```
0 1 2 3
1 2.0 5.0 8 NaN
```
هنا، تم إزالة الصف الأول والأخير، لأنهما يحتويان فقط على قيمتين غير فارغتين.
- **ملء القيم الفارغة**: اعتمادًا على مجموعة البيانات الخاصة بك، قد يكون من المنطقي أحيانًا ملء القيم الفارغة بقيم صالحة بدلاً من إزالتها. يمكنك استخدام `isnull` للقيام بذلك في المكان، ولكن يمكن أن يكون ذلك مرهقًا، خصوصًا إذا كان لديك الكثير من القيم لملئها. نظرًا لأن هذه مهمة شائعة جدًا في علم البيانات، توفر pandas `fillna`، التي تعيد نسخة من `Series` أو `DataFrame` مع استبدال القيم المفقودة بواحدة من اختيارك. دعونا ننشئ مثالًا آخر لـ `Series` لرؤية كيفية عمل هذا عمليًا.
```python
example3 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))
example3
```
```
a 1.0
b NaN
c 2.0
d NaN
e 3.0
dtype: float64
```
يمكنك ملء جميع الإدخالات الفارغة بقيمة واحدة، مثل `0`:
```python
example3.fillna(0)
```
```
a 1.0
b 0.0
c 2.0
d 0.0
e 3.0
dtype: float64
```
يمكنك **ملء القيم الفارغة للأمام**، وهو استخدام القيمة الصالحة الأخيرة لملء الفارغ:
```python
example3.fillna(method='ffill')
```
```
a 1.0
b 1.0
c 2.0
d 2.0
e 3.0
dtype: float64
```
يمكنك أيضًا **ملء القيم الفارغة للخلف** لنشر القيمة الصالحة التالية للخلف لملء الفارغ:
```python
example3.fillna(method='bfill')
```
```
a 1.0
b 2.0
c 2.0
d 3.0
e 3.0
dtype: float64
```
كما قد تتوقع، يعمل هذا بنفس الطريقة مع `DataFrame`s، ولكن يمكنك أيضًا تحديد `axis` على طول ملء القيم الفارغة. باستخدام `example2` الذي تم استخدامه سابقًا:
```python
example2.fillna(method='ffill', axis=1)
```
```
0 1 2 3
0 1.0 1.0 7.0 7.0
1 2.0 5.0 8.0 8.0
2 NaN 6.0 9.0 9.0
```
لاحظ أنه عندما لا تكون هناك قيمة سابقة متاحة للملء الأمامي، تبقى القيمة الفارغة.
> **الخلاصة:** هناك طرق متعددة للتعامل مع القيم المفقودة في مجموعات البيانات الخاصة بك. يجب أن تكون الاستراتيجية المحددة التي تستخدمها (إزالتها، استبدالها، أو حتى كيفية استبدالها) مستندة إلى خصائص تلك البيانات. ستكتسب فهمًا أفضل لكيفية التعامل مع القيم المفقودة كلما تعاملت وتفاعلت أكثر مع مجموعات البيانات.
## إزالة البيانات المكررة
> **هدف التعلم:** بنهاية هذا القسم، يجب أن تكون قادرًا على التعرف على القيم المكررة وإزالتها من DataFrames.
بالإضافة إلى البيانات المفقودة، ستواجه غالبًا بيانات مكررة في مجموعات البيانات الواقعية. لحسن الحظ، يوفر `pandas` طريقة سهلة لاكتشاف وإزالة الإدخالات المكررة.
- **التعرف على التكرارات: `duplicated`**: يمكنك بسهولة تحديد القيم المكررة باستخدام طريقة `duplicated` في pandas، والتي تُرجع قناعًا منطقيًا يشير إلى ما إذا كان الإدخال في `DataFrame` مكررًا لإدخال سابق. لنقم بإنشاء مثال آخر لـ `DataFrame` لرؤية ذلك عمليًا.
```python
example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],
'numbers': [1, 2, 1, 3, 3]})
example4
```
| |letters|numbers|
|------|-------|-------|
|0 |A |1 |
|1 |B |2 |
|2 |A |1 |
|3 |B |3 |
|4 |B |3 |
```python
example4.duplicated()
```
```
0 False
1 False
2 True
3 False
4 True
dtype: bool
```
- **إزالة التكرارات: `drop_duplicates`:** ببساطة تُرجع نسخة من البيانات التي تكون فيها جميع القيم المكررة `False`:
```python
example4.drop_duplicates()
```
```
letters numbers
0 A 1
1 B 2
3 B 3
```
كل من `duplicated` و `drop_duplicates` تفترض افتراضيًا النظر في جميع الأعمدة، ولكن يمكنك تحديد أن يتم فحص مجموعة فرعية فقط من الأعمدة في `DataFrame` الخاص بك:
```python
example4.drop_duplicates(['letters'])
```
```
letters numbers
0 A 1
1 B 2
```
> **الخلاصة:** إزالة البيانات المكررة جزء أساسي من كل مشروع علم بيانات تقريبًا. يمكن للبيانات المكررة أن تغير نتائج تحليلاتك وتمنحك نتائج غير دقيقة!
## 🚀 التحدي
جميع المواد التي تمت مناقشتها متوفرة كـ [Jupyter Notebook](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/2-Working-With-Data/08-data-preparation/notebook.ipynb). بالإضافة إلى ذلك، هناك تمارين موجودة بعد كل قسم، جربها!
## [اختبار ما بعد المحاضرة](https://ff-quizzes.netlify.app/en/ds/quiz/15)
## المراجعة والدراسة الذاتية
هناك العديد من الطرق لاكتشاف وتحضير بياناتك للتحليل والنمذجة، وتنظيف البيانات خطوة مهمة تتطلب تجربة عملية. جرب هذه التحديات من Kaggle لاستكشاف تقنيات لم يتم تغطيتها في هذا الدرس.
- [تحدي تنظيف البيانات: تحليل التواريخ](https://www.kaggle.com/rtatman/data-cleaning-challenge-parsing-dates/)
- [تحدي تنظيف البيانات: قياس وتطبيع البيانات](https://www.kaggle.com/rtatman/data-cleaning-challenge-scale-and-normalize-data)
## الواجب
[تقييم البيانات من نموذج](assignment.md)
---
**إخلاء المسؤولية**:
تم ترجمة هذا المستند باستخدام خدمة الترجمة بالذكاء الاصطناعي [Co-op Translator](https://github.com/Azure/co-op-translator). بينما نسعى لتحقيق الدقة، يرجى العلم أن الترجمات الآلية قد تحتوي على أخطاء أو معلومات غير دقيقة. يجب اعتبار المستند الأصلي بلغته الأصلية المصدر الرسمي. للحصول على معلومات حاسمة، يُوصى بالاستعانة بترجمة بشرية احترافية. نحن غير مسؤولين عن أي سوء فهم أو تفسيرات خاطئة ناتجة عن استخدام هذه الترجمة.