FA-TOOLS — Header Component

پاکسازی داده با pandas — حذف null و تکراری

رفیق برنامه‌نویس، می‌دونم که سروکله زدن با داده‌های کثیف چقدر می‌تونه خسته‌کننده باشه. اگه دنبال راهی هستی که داده‌هاتو برق بندازی و باهاش معجزه کنی، جای درستی اومدی! تو این مقاله قراره با هم یاد بگیریم چطور با جادوی Pandas، داده‌های Null و تکراری رو از بین ببریم و یه دیتاست تمیز و آماده تحلیل داشته باشیم. برای شروع کار و دسترسی به کلی ابزار کاربردی و اسنیپت‌های خفن، حتماً یه سری به فروشگاه ابزارهای برنامه‌نویسی ما بزن؛ قول میدم دست خالی برنمی‌گردی!

برای هرگونه راهنمایی یا مشاوره، با این شماره تماس بگیرید: 09202232789

🗺️ نقشه راه پاکسازی داده با Pandas در یک نگاه

پاکسازی داده با pandas — حذف null و تکراری — تصویر 1

🛠️ مرحله ۱: آماده‌سازی

  • ✅ نصب و ایمپورت Pandas
  • ✅ بارگذاری دیتاست

🗑️ مرحله ۲: حذف Null ها

  • 🔍 شناسایی: `isna()`, `isnull()`, `sum()`
  • 🧹 استراتژی‌ها: `dropna()`, `fillna()`

🔄 مرحله ۳: مدیریت تکراری‌ها

  • 🕵️ شناسایی: `duplicated()`, `sum()`
  • 🔪 حذف: `drop_duplicates()`

💡 مرحله ۴: بهترین شیوه‌ها

  • 🚀 پاکسازی پیشرفته
  • 💾 پشتیبان‌گیری
  • ⚙️ عیب‌یابی سریع

چرا پاکسازی داده حیاتیه؟

داده، نفت عصر حاضره؛ اما یه نفت تصفیه نشده به درد هیچ‌کس نمی‌خوره. تو دنیای برنامه‌نویسی و تحلیل داده، اگه اطلاعاتی که باهاش کار می‌کنی کثیف باشن، نتایجی که می‌گیری هم بی‌اعتبار و گمراه‌کننده میشن. تصور کن یه گزارش مهم قراره بدی، ولی پایه‌های گزارشت روی داده‌های پر از سوراخ و اشتباهات بنا شده باشه. فاجعه‌ست، نه؟

داده‌های کثیف یعنی چی؟

خیلی ساده بگم، داده کثیف یعنی هر چیزی که مانع تحلیل درست و دقیق میشه. این کثیفی می‌تونه شامل موارد زیر باشه:

  • مقادیر Null (گمشده): جاهایی که باید اطلاعاتی وجود داشته باشه ولی نیست. مثل وقتی که مشتری آدرسشو وارد نکرده.
  • داده‌های تکراری: دو یا چند ردیف که کاملاً شبیه همن و یه اطلاعات رو چند بار تکرار می‌کنن. مثلاً یه کاربر دوبار تو لیست ثبت شده.
  • خطاهای فرمت‌بندی: تاریخ‌هایی که یه جا به میلادی وارد شدن یه جا به شمسی، یا اعداد که به جای عدد به صورت متن ذخیره شدن.
  • ناهماهنگی‌ها: مثلاً یه جا اسم شهر “تهران” نوشته شده، یه جای دیگه “Tehran”.

مزایای داده‌های تمیز

اگه داده‌هات تمیز و مرتب باشن، انگار یه سوپرشارژر به پروژه اضافه کردی! اینا فقط چند تا از مزایاشه:

  • 🚀 نتایج دقیق‌تر: مدل‌های یادگیری ماشین و تحلیل‌های آماریت دقیق‌تر میشن.
  • ⏱️ صرفه‌جویی در زمان: دیگه لازم نیست ساعت‌ها دنبال اشکالات بگردی.
  • 🤝 اعتماد بیشتر: به گزارش‌ها و تصمیماتی که بر اساس داده‌ها می‌گیری، اعتماد بیشتری پیدا می‌کنی.
  • 📈 کارایی بالاتر: کل فرآیند تحلیل دادهت روان‌تر و پربازده‌تر میشه.

آماده‌سازی محیط کار با Pandas

قبل از اینکه وارد دنیای پر هیجان پاکسازی بشیم، باید مطمئن بشیم که ابزارهامون آماده‌ان. پایتون و کتابخانه پاناداس (Pandas) مثل چاقوی سوئیسی برای هر تحلیل‌گر داده هستن.

نصب و ایمپورت Pandas

اگه هنوز Pandas رو نصب نکردی، یه خط کد ساده تو ترمینال کارو را میندازه:

pip install pandas numpy

بعد از نصب، برای استفاده ازش، کافیه ایمپورتش کنی:

import pandas as pd
import numpy as np # معمولاً کنار pandas استفاده میشه

بارگذاری داده‌ها (مثال)

برای اینکه بتونیم چیزی رو پاکسازی کنیم، اول باید اونو لود کنیم. اکثر اوقات با فایل‌های CSV سروکار داریم، اما Pandas فرمت‌های دیگه‌ای مثل Excel, SQL و JSON رو هم پشتیبانی می‌کنه.

# فرض می‌کنیم یه فایل به اسم 'sample_data.csv' داریم
# اگه فایلی نداری، می‌تونی یه دیتافریم نمونه بسازی
data = {
    'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
    'Name': ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Alice', 'Frank', 'Grace', 'Charlie', 'Heidi'],
    'Age': [24, 30, np.nan, 28, 22, 24, 35, np.nan, 26, 29],
    'City': ['NY', 'LA', 'Chicago', 'NY', 'Boston', 'NY', 'Miami', 'LA', 'Chicago', np.nan],
    'Salary': [50000, 60000, 75000, np.nan, 55000, 50000, 80000, 62000, 75000, 70000]
}
df = pd.DataFrame(data)

print("دیتافریم اولیه:")
print(df)
print("nاطلاعات دیتافریم:")
print(df.info())
print("nتوصیف آماری:")
print(df.describe())

اینجا `np.nan` نشون‌دهنده مقادیر گمشده یا Null هست که قراره باهاش سر و کله بزنیم.

حذف داده‌های Null (مقادیر گمشده)

اولین چالش ما، مقادیر Null هستن. این مقادیر می‌تونن باعث خطا تو محاسبات بشن یا مدل‌های پیش‌بینی رو خراب کنن. باید باهاشون هوشمندانه برخورد کنیم.

شناسائی مقادیر Null

قبل از هر اقدامی، باید بدونیم اصلاً کجاها Null داریم و تعدادشون چقدره. تو Pandas دو تا تابع فوق‌العاده برای این کار هست: `isna()` و `isnull()` که هر دو کار مشابهی انجام میدن.

  • `df.isna()` یا `df.isnull()`: یه دیتافریم بولی برمی‌گردونه که توش `True` یعنی اون خونه Null هست و `False` یعنی مقدار داره.
  • `df.isna().sum()`: این یکی خیلی کاربردیه! میاد تعداد Nullها رو برای هر ستون بهت میگه. یه نگاه سریع به وضعیت داده‌هات.
print("nمقادیر Null در دیتافریم (True = Null):")
print(df.isna())

print("nتعداد مقادیر Null برای هر ستون:")
print(df.isna().sum())

با این خروجی، می‌فهمیم که ستون‌های ‘Age’ و ‘City’ و ‘Salary’ مقادیر Null دارن و تعدادشون هم چقدره.

استراتژی‌های حذذف Null

حالا که می‌دونیم Nullها کجا قایم شدن، وقتشه که یه کاری باهاشون بکنیم. دو روش اصلی داریم: حذف کردنشون یا پر کردنشون.

روش ۱: حذف ردیف‌ها یا ستون‌ها (`dropna()`)

ساده‌ترین راه اینه که هر ردیفی یا ستونی که Null داره رو کلاً بندازیم دور. البته این روش همیشه بهترین نیست، چون ممکنه داده‌های مهمی رو از دست بدی. از تابع `dropna()` برای این کار استفاده می‌کنیم.

  • `how=’any’` (پیش‌فرض): هر ردیفی که حداقل یه Null داشته باشه حذف میشه.
  • `how=’all’`: فقط ردیف‌هایی حذف میشن که همه‌ی مقادیرشون Null باشن.
  • `axis=0` (پیش‌فرض): ردیف‌ها حذف میشن. `axis=1` برای حذف ستون‌هاست.
  • `subset=[‘col1’, ‘col2’]`: فقط تو ستون‌های مشخص شده Nullها رو بررسی می‌کنه.
  • `inplace=True`: تغییرات رو مستقیم رو خود دیتافریم اعمال می‌کنه، وگرنه یه کپی جدید برمی‌گردونه.
# مثال ۱: حذف ردیف‌هایی که حداقل یک Null دارن
df_dropped_any = df.dropna()
print("nدیتافریم بعد از حذف ردیف‌های با حداقل یک Null:")
print(df_dropped_any)

# مثال ۲: حذف ردیف‌هایی که فقط در ستون 'Age' یا 'City' Null دارن
df_dropped_subset = df.dropna(subset=['Age', 'City'])
print("nدیتافریم بعد از حذف Null در ستون‌های خاص ('Age', 'City'):")
print(df_dropped_subset)

می‌بینی که چقدر ردیف‌ها کمتر شدن؟ این یعنی از دست دادن اطلاعات. همیشه اول وضعیت Nullها رو خوب بررسی کن بعد تصمیم بگیر که حذفشون کنی یا پرشون کنی.

روش ۲: جایگزینی مقادیر Null (`fillna()`)

این روش که بهش Imputation هم میگن، انعطاف‌پذیرتره. تو این حالت، Nullها رو با یه مقدار منطقی جایگزین می‌کنیم. این مقدار می‌تونه یه عدد ثابت، میانگین، میانه، مد، یا حتی مقادیر قبلی یا بعدی باشه.

جایگزینی با مقدار ثابت
# کپی گرفتن از دیتافریم اصلی برای اعمال تغییرات جدید
df_filled = df.copy()

# جایگزینی Null های ستون 'City' با 'Unknown'
df_filled['City'].fillna('Unknown', inplace=True)
print("nدیتافریم بعد از جایگزینی Null های 'City' با 'Unknown':")
print(df_filled)
جایگزینی با میانگین (Mean)، میانه (Median) یا مد (Mode)

این روش برای ستون‌های عددی خیلی کاربردیه. میانگین برای داده‌های متقارن و میانه برای داده‌های با کج‌شدگی (skewed data) مناسب‌تره. مد هم برای داده‌های دسته‌ای (categorical) عالیه.

# پر کردن Null های 'Age' با میانگین Age
mean_age = df_filled['Age'].mean()
df_filled['Age'].fillna(mean_age, inplace=True)

# پر کردن Null های 'Salary' با میانه Salary
median_salary = df_filled['Salary'].median()
df_filled['Salary'].fillna(median_salary, inplace=True)

print("nدیتافریم بعد از جایگزینی Null های 'Age' (میانگین) و 'Salary' (میانه):")
print(df_filled)
print("nتعداد Null ها بعد از جایگزینی:")
print(df_filled.isna().sum())
جایگزینی با روش‌های پیشین/پسین (`ffill`, `bfill`)

گاهی اوقات می‌خوایم یه Null رو با مقدار معتبر قبلیش (Forward Fill یا `ffill`) یا بعدی‌ش (Backward Fill یا `bfill`) پر کنیم. این روش برای داده‌های سری زمانی یا وقتی که ترتیب ردیف‌ها مهمه، خیلی مفیده.

# فرض کن یه سری زمانی داریم که توش Null هست
s = pd.Series([1, np.nan, 3, np.nan, 5])
print("nسری زمانی اصلی:")
print(s)

s_ffill = s.ffill()
print("nسری زمانی بعد از ffill:")
print(s_ffill)

s_bfill = s.bfill()
print("nسری زمانی بعد از bfill:")
print(s_bfill)

جدول مقایسه روش‌های مدیریت Null

روش توضیحات و کاربرد
`dropna()` حذف ردیف‌ها یا ستون‌های حاوی Null. سریع و ساده، اما ممکن است منجر به از دست رفتن داده شود. برای حجم کم Null یا زمانی که دقت بالا ضروری است.
`fillna(value)` پر کردن Null ها با یک مقدار ثابت (مثلاً 0، ‘Unknown’). مناسب برای داده‌های دسته‌ای یا وقتی مقدار خاصی منطقی است.
`fillna(df.mean())` پر کردن Null ها با میانگین ستون. برای داده‌های عددی که توزیع نرمال دارند. حساس به Outlierها.
`fillna(df.median())` پر کردن Null ها با میانه ستون. برای داده‌های عددی که دارای کج‌شدگی (skew) هستند یا Outlier دارند.
`fillna(df.mode()[0])` پر کردن Null ها با مد ستون. مناسب برای داده‌های دسته‌ای یا عددی با تعداد محدود مقادیر منحصر به فرد.
`ffill()` / `bfill()` پر کردن با مقدار قبلی (forward fill) یا بعدی (backward fill). ایده‌آل برای سری‌های زمانی یا داده‌هایی که ترتیب اهمیت دارد.

انتخاب روش مناسب بستگی به نوع داده و هدف تحلیل شما دارد.

مدیریت داده‌های تکراری

داده‌های تکراری هم مثل Nullها، می‌تونن باعث مشکل بشن. مثلاً اگه یه کاربر دو بار تو لیست ثبت شده باشه، تحلیل‌های مشتری‌مداریت رو حسابی بهم می‌ریزه. Pandas ابزارهای قوی برای شناسایی و حذذف این مشکل رو داره.

شناسایی ردیف‌های تکراری

تابع `duplicated()` قهرمان این بخش ماست. این تابع یه سری بولی برمی‌گردونه که `True` یعنی اون ردیف یه کپی از یه ردیف قبلیه و `False` یعنی منحصر به فرده.

  • `df.duplicated()`: ردیف‌های تکراری رو بعد از اولین وقوع نشون میده.
  • `df.duplicated().sum()`: تعداد کل ردیف‌های تکراری رو می‌شمره.
  • `subset=[‘col1’, ‘col2’]`: فقط تکراری بودن رو بر اساس مقادیر ستون‌های مشخص شده بررسی می‌کنه.
# از دیتافریم اولیه (df) استفاده می‌کنیم که Alice و Charlie تکراری دارن
print("nشناسایی ردیف‌های تکراری:")
print(df.duplicated())

print("nتعداد ردیف‌های تکراری:")
print(df.duplicated().sum())

# شناسایی تکراری‌ها فقط بر اساس ستون 'Name'
print("nشناسایی تکراری‌ها فقط بر اساس 'Name':")
print(df.duplicated(subset=['Name']))

# نمایش ردیف‌های تکراری
print("nنمایش ردیف‌های تکراری:")
print(df[df.duplicated()])

همونطور که می‌بینی، `Alice` در ردیف ۶ و `Charlie` در ردیف ۹ به عنوان تکراری شناسایی شدن (با فرض اینکه `keep=’first’` هست که پیش‌فرضه).

حذف ردیف‌های تکراری

وقتی تکراری‌ها رو شناسایی کردی، حذفشون با `drop_duplicates()` خیلی راحته. این تابع هم مثل `dropna()` پارامترهای مشابهی داره.

  • `keep=’first’` (پیش‌فرض): اولین وقوع رو نگه می‌داره و بقیه‌ی تکراری‌ها رو حذف می‌کنه.
  • `keep=’last’`: آخرین وقوع رو نگه می‌داره.
  • `keep=False`: همه‌ی ردیف‌هایی که تکراری هستن رو حذف می‌کنه (حتی اولین وقوع).
  • `subset=[‘col1’, ‘col2’]`: تکراری بودن رو بر اساس این ستون‌ها بررسی می‌کنه.
  • `inplace=True`: تغییرات رو رو خود دیتافریم اعمال می‌کنه.
# حذف ردیف‌های کاملاً تکراری
df_deduplicated = df.drop_duplicates()
print("nدیتافریم بعد از حذف ردیف‌های کاملاً تکراری:")
print(df_deduplicated)

# حذف تکراری‌ها فقط بر اساس ستون 'Name' (اولین وقوع رو نگه می‌داره)
df_deduplicated_name = df.drop_duplicates(subset=['Name'], keep='first')
print("nدیتافریم بعد از حذف تکراری‌ها بر اساس 'Name':")
print(df_deduplicated_name)

# حذف تکراری‌ها بر اساس 'Name' و 'Age'
df_deduplicated_name_age = df.drop_duplicates(subset=['Name', 'Age'], keep='first')
print("nدیتافریم بعد از حذف تکراری‌ها بر اساس 'Name' و 'Age':")
print(df_deduplicated_name_age)

همینطور که می‌بینی، با استفاده از `subset` می‌تونیم کنترل دقیق‌تری رو فرآیند حذف تکراری‌ها داشته باشیم. مثلاً اگه دو نفر اسمشون ‘علی’ باشه ولی IDهای مختلفی داشته باشن، اگه فقط بر اساس ‘Name’ حذف کنیم، یکیشون حذف میشه که ممکنه اشتباه باشه. بنابراین، همیشه خوب فکر کن که چه ستون‌هایی واقعاً معرف تکراری بودن هستن.

نکات پیشرفته و بهترین شیوه‌ها

پاکسازی داده فقط حذف Null و تکراری نیست، بلکه یه فرآیند مستمر و هوشمندانه است. بیا چند تا نکته حرفه‌ای رو مرور کنیم.

پاکسازی پیشرفته‌تر (Whitespace, فرمت‌بندی)

اغلب اوقات، مشکلات داده فقط Null و تکراری نیستن. ممکنه فضاهای خالی اضافه (whitespace) تو متن‌ها، حروف کوچیک و بزرگ ناهماهنگ، یا فرمت‌های عددی و تاریخ اشتباه داشته باشی. این‌ها هم نیاز به پاکسازی دارن.

  • حذف Whitespace: `df[‘Column’].str.strip()` خیلی کارآمده.
  • یکسان‌سازی حروف: `df[‘Column’].str.lower()` یا `df[‘Column’].str.upper()` برای یکسان کردن متن‌ها.
  • تبدیل نوع داده: `pd.to_numeric()`, `pd.to_datetime()` برای اطمینان از صحت نوع داده. برای اسنیپت‌های مفیدتر تو حوزه کدهای آماده حتما سر بزن.

اهمیت پشتیبان‌گیری

قبل از اینکه هر تغییر بزرگی رو روی دیتاستت اعمال کنی، یه کپی ازش بگیر. مثل یه برنامه‌نویس باهوش، همیشه حواست به بک‌آپ باشه! با `df.copy()` می‌تونی یه کپی عمیق از دیتافریم بگیری که تغییرات روی اون، رو دیتافریم اصلی تاثیر نذاره.

گردش کار تکراری (Iterative Workflow)

پاکسازی داده یه فرآیند خطی نیست. ممکنه Null ها رو پر کنی، بعد ببینی که داده‌های تکراری جدیدی به وجود اومدن یا برعکس. پس همیشه این چرخه رو تو ذهنت داشته باش: شناسایی ➔ تحلیل ➔ اقدام ➔ بررسی مجدد.

🚨 عیب‌یابی سریع (Troubleshooting)

حتی حرفه‌ای‌ها هم گاهی تو پاکسازی داده به مشکل می‌خورن. اینا چند تا سناریو رایج و راه‌حل‌هاشون هست:

  • مشکل: “بعد از `df.dropna()` هنوز Null دارم!”

    راه‌حل: احتمالاً `inplace=True` رو فراموش کردی. تابع `dropna()` به صورت پیش‌فرض یه کپی جدید برمی‌گردونه. یا ممکنه داده‌های Null با فرمت‌های دیگه‌ای (مثل ‘NaN’ به صورت رشته) باشن که Pandas اونا رو Null واقعی شناسایی نمی‌کنه. تو این حالت، اول باید اونا رو به `np.nan` تبدیل کنی: `df.replace(‘NaN’, np.nan, inplace=True)`.

  • مشکل: “ردیف‌های تکراری من حذف نمیشن، یا فقط بخشی از اونا حذف میشه!”

    راه‌حل: پارامتر `subset` رو درست تنظیم نکردی. اگه می‌خوای بر اساس تمام ستون‌ها تکراری‌ها رو حذف کنی، `subset` رو خالی بذار. اگه بر اساس چند ستون خاصه، مطمئن شو که همه ستون‌های کلیدی رو تو لیست `subset` آوردی. همچنین `inplace=True` رو بررسی کن و مقدار `keep` (first, last, False) رو متناسب با نیازت انتخاب کن.

  • مشکل: “میانگین‌گیری برای پر کردن Nullها داده‌های من رو خراب می‌کنه!” (مثلاً میانگین سن 25.75 شده اما سن نباید اعشار داشته باشد)

    راه‌حل: اینجاست که باید از میانگین به سمت میانه (median) یا مد (mode) بری. میانه نسبت به مقادیر پرت (outliers) مقاوم‌تره و کمتر داده‌هاتو تحت تاثیر قرار میده. همچنین بعد از پر کردن می‌تونی ستون رو به عدد صحیح (integer) تبدیل کنی: `df[‘Age’] = df[‘Age’].astype(int)`.

  • مشکل: “پاکسازی داده زمان‌بر و پیچیده‌ست!”

    راه‌حل: این طبیعیه! پاکسازی داده اغلب بیشترین زمان رو تو فرآیند تحلیل داده می‌بره. سعی کن یه تابع (function) برای کارهای تکراریت بنویسی و از اسنیپت‌های پایتون موجود استفاده کنی تا کار رو سریع‌تر پیش ببری. گام‌های کوچیک بردار و هر مرحله رو تست کن.

❓ پاسخ به سوالات متداول (FAQ)

  • فرق `isna()` و `isnull()` چیه؟

    هیچ فرقی! هر دو alias (نام مستعار) همدیگه‌ان و کاملاً یک کار رو انجام میدن. می‌تونی از هر کدوم که راحت‌تری استفاده کنی.

  • چطور بفهمم کدوم روش پر کردن Null بهتره؟

    بستگی به نوع داده و هدفت داره. اگه داده‌هات عددی و نرمال هستن، میانگین خوبه. اگه outliers زیاد دارن، میانه بهتره. برای داده‌های دسته‌ای (متنی) مد یا یه مقدار ثابت مثل ‘Unknown’ مناسب‌تره. همیشه سعی کن تاثیر روش انتخابی رو روی مدل یا تحلیل نهایی‌ت بررسی کنی.

  • آیا باید همیشه تمام Null ها و تکراری‌ها رو حذف کنم؟

    نه لزوماً. گاهی اوقات، خود وجود Nullها می‌تونه یه اطلاعات مهم باشه. یا ممکنه داده‌های تکراری در واقع رکورد‌های جداگانه باشن (مثلاً خریدهای متعدد یک مشتری در زمان‌های مختلف). همیشه قبل از حذف، ماهیت داده و معنی Null یا تکراری بودن رو درک کن.

  • چگونه می‌توانم از بروز داده‌های کثیف در آینده جلوگیری کنم؟

    این یک سوال عالی است! بهترین راه حل از مبدا شروع می‌شود. طراحی دیتابیس صحیح، اعتبارسنجی ورودی (Input Validation) در فرم‌ها و API ها، و استفاده از فرمت‌های استاندارد برای ذخیره‌سازی داده‌ها از جمله کارهایی هستند که می‌توانند به صورت چشمگیری میزان داده‌های کثیف را کاهش دهند. همچنین، نظارت منظم و خودکار بر کیفیت داده‌ها می‌تواند کمک کننده باشد.

خب رفقا، دیدین که پاکسازی داده با Pandas اونقدرها هم ترسناک نیست! با این ابزارای قدرتمند، می‌تونیم داده‌هامونو از یه توده اطلاعات به هم ریخته به یه منبع ارزشمند برای تحلیل و تصمیم‌گیری تبدیل کنیم. پس دیگه بهونه‌ای برای سروکله زدن با داده‌های کثیف نداریم. شروع کن و داده‌هاتو برق بنداز! اگه سوالی داشتی، فراموش نکن که بخش اسنیپت‌های ما همیشه برای کمک آماده‌ست.

Table of Contents

آخرین نوشته‌ها