سرنخ — خودآموز برنامه‌نویسی برای هوش مصنوعی (مقدماتی)

فصل ۶ از ۱۰

پیشرفت ترم
۰٪

ترم ۲ · داده: دیدن، تمیز کردن، فهمیدن

گروه‌بندی: از ردیف به بینش

فصل ۶پیش‌نمایش رایگان

در این فصل چه یاد می‌گیری#

جدولِ تمیزت ۲۳۸ ردیف دارد. هیچ‌کس نمی‌تواند ۲۳۸ ردیف را نگاه کند و بفهمد چه خبر است. کاری که می‌کنی این است: ردیف‌ها را گروه می‌کنی و از هر گروه یک عدد می‌گیری — «میانگینِ قیمتِ هر برند»، «تعدادِ آگهی در هر شهر». در این فصل groupby را یاد می‌گیری، پرکاربردترین ابزارِ تحلیلِ داده، و همان‌جا می‌بینی چطور یک جدولِ ۲۳۸ ردیفی در سه خط به یک جدولِ پنج‌ردیفیِ کاملاً گویا تبدیل می‌شود.

یک سینیِ مرتب‌سازی که اشیاء درهم را به پنج ستونِ جدا هدایت می‌کند و بالای هر ستون یک ترازوی کوچک ایستاده

آخر این فصل می‌توانی:

  • با groupby داده را گروه کنی و از هر گروه یک عدد بگیری
  • با agg چند آمار را همزمان بگیری
  • روی دو ستون همزمان گروه‌بندی کنی
  • با pivot_table جدولِ دوبعدی بسازی
  • بگویی چرا count هر گروه به‌اندازهٔ mean آن مهم است

قبل از شروع#

از فصل ۵: جدولِ تمیز. سلولِ راه‌اندازی همان پنج قدمِ پاک‌سازی را تکرار می‌کند و فایلِ laptops_clean.csv را می‌سازد، تا لازم نباشد هر فصل از نو پاک‌سازی کنی.

از ترمِ ۱ فصل ۶: الگوی انباشتگر — groupby دقیقاً همان کار را می‌کند، فقط برای هر گروه جداگانه.

📓 نوت‌بوک: نوت‌بوک این فصل را در Colab باز کن — همهٔ کدهای این فصل آماده و به‌ترتیب داخلش هست.

۱. اولین گروه‌بندی#

import pandas as pd

df = pd.read_csv("laptops_clean.csv")

print(df.groupby("brand")["price"].mean().round(0))
brand
اپل      46025000.0
اچ پی    23540000.0
ایسوس    24893506.0
دل       22451111.0
لنوو     23745833.0
Name: price, dtype: float64

این خط را از چپ بخوان: «جدول را بر اساسِ brand گروه کن، از هر گروه ستونِ price را بردار، و میانگینش را بگیر».

۲۳۸ ردیف شد پنج عدد، و همان پنج عدد چیزی می‌گویند که هیچ‌کس با نگاه‌کردن به ردیف‌ها نمی‌فهمید: اپل تقریباً دو برابرِ بقیه است.

الگوی groupby همیشه سه تکه دارد و به آن تقسیم-اعمال-ترکیب می‌گویند: داده به گروه‌ها تقسیم می‌شود، روی هر گروه یک تابع اعمال می‌شود، و نتیجه‌ها در یک جدول ترکیب می‌شوند.

⚠️ مواظب باش: اگر فصلِ ۵ را انجام نداده بودی و روی دادهٔ خام گروه‌بندی می‌کردی، هفت گروه می‌گرفتی نه پنج — «ایسوس» و «ايسوس» جدا می‌شدند و میانگینِ هر دو غلط می‌شد. گروه‌بندی روی دادهٔ تمیزنشده، بدترین جایی است که کثیفیِ متن خودش را نشان می‌دهد، چون نتیجه‌اش کاملاً منطقی به‌نظر می‌رسد.

۲. agg: چند آمار با هم#

یک عدد در هر گروه کافی نیست:

summary = df.groupby("brand")["price"].agg(["count", "mean", "median"]).round(0)
print(summary)
       count        mean      median
brand
اپل       28  46025000.0  45050000.0
اچ پی     40  23540000.0  23750000.0
ایسوس     77  24893506.0  25100000.0
دل        45  22451111.0  22200000.0
لنوو      48  23745833.0  22100000.0

حالا تصویر کامل‌تر است. agg یک فهرست از نامِ تابع‌ها می‌گیرد و برای هرکدام یک ستون می‌سازد.

📏 اندازه بگیر: ستونِ count را جدی بگیر — به‌اندازهٔ mean مهم است و تقریباً همیشه جا می‌افتد. اپل فقط ۲۸ آگهی دارد در برابرِ ۷۷ آگهیِ ایسوس. یعنی میانگینِ اپل روی نمونهٔ کوچک‌تری حساب شده و بی‌ثبات‌تر است: یک آگهیِ عجیب، میانگینِ ۲۸تایی را خیلی بیشتر تکان می‌دهد تا ۷۷تایی را. هر وقت میانگینِ یک گروه را گزارش کردی، تعدادش را هم گزارش کن. میانگینی که تعدادش را نمی‌دانی، عددی است که نمی‌دانی چقدر باید باورش کنی.

و به فاصلهٔ mean و median نگاه کن. برای «لنوو» میانگین ۲۳٫۷ میلیون است ولی میانه ۲۲٫۱ — یعنی چند آگهیِ گران، میانگین را بالا کشیده‌اند. هر جا این دو از هم فاصله بگیرند، توزیع متقارن نیست.

🌱 ریشه‌اش کجاست: اینکه چرا میانگین با یک مقدارِ بزرگ جابه‌جا می‌شود ولی میانه تقریباً بی‌حرکت می‌ماند، دقیقاً موضوعِ ریشه، ترم ۶ فصل ۶ — میانگین، میانه، پراکندگی است.

۳. گروه‌بندی روی دو ستون#

by_brand_city = df.groupby(["brand", "city"])["price"].mean().round(0)
print(by_brand_city.head(6))
brand  city
اپل    اصفهان    49400000.0
       تبریز     39966667.0
       تهران     47826667.0
       شیراز     40133333.0
       مشهد      45700000.0
اچ پی  اصفهان    27400000.0
Name: price, dtype: float64

با دادنِ یک list از نامِ ستون‌ها، هر ترکیب یک گروه می‌شود. نتیجه اندیسِ دوطبقه دارد: اول برند، بعد شهر.

این خوانا هست ولی برای مقایسه ایده‌آل نیست — سخت است بفهمی کدام شهر برای همهٔ برندها گران‌تر است. برای آن، شکلِ دوبعدی بهتر است.

۴. pivot_table: جدولِ دوبعدی#

pivot = df.pivot_table(values="price", index="brand", columns="year", aggfunc="mean").round(0)
print(pivot.iloc[:, :4])
year         2016        2017        2018        2019
brand
اپل    36000000.0  37450000.0  40925000.0  41300000.0
اچ پی  14600000.0  16540000.0  17100000.0  22166667.0
ایسوس  14683333.0  15150000.0  18085714.0  21242857.0
دل     13750000.0  18133333.0  19760000.0  19028571.0
لنوو   14355556.0  14525000.0  18440000.0  20233333.0

pivot_table چهار چیز می‌خواهد: چه چیزی را تجمیع کند (values)، چه چیزی ردیف شود (index)، چه چیزی ستون شود (columns)، و با چه تابعی (aggfunc).

فقط چهار ستونِ اول را نشان دادیم چون نُه سالِ کامل در صفحه جا نمی‌شود. حتی در همین چهار ستون، دو الگو دیده می‌شود: قیمت‌ها با سال بالا می‌روند و اپل در همهٔ سال‌ها بالاتر است.

چک کن: جدولِ تو باید پنج ردیف داشته باشد (پنج برند) و هر عددش مثبت و در محدودهٔ ده تا شصت میلیون باشد. اگر خانهٔ خالی (NaN) دیدی، یعنی آن ترکیبِ برند-سال هیچ آگهی‌ای ندارد — که کاملاً عادی است و خودش یک اطلاعات است.

۵. روند در طولِ زمان#

by_year = df.groupby("year")["price"].mean().round(0)
print(by_year)
year
2016    17226667.0
2017    17786364.0
2018    21988000.0
2019    23173913.0
2020    25040000.0
2021    30970968.0
2022    30440000.0
2023    35060714.0
2024    36641667.0
Name: price, dtype: float64

یک روندِ تقریباً یکنواختِ صعودی. از ۱۷٫۲ میلیون در ۲۰۱۶ به ۳۶٫۶ میلیون در ۲۰۲۴ — بیش از دو برابر.

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

۶. یک خطای واقعی: گروه‌بندی روی ستونی که نیست#

df.groupby("Brand")["price"].mean()
KeyError: 'Brand'

حرفِ اولِ بزرگ. نامِ ستون‌ها به بزرگی و کوچکیِ حروف حساس‌اند و pandas هیچ حدسی نمی‌زند. این همان KeyError آشنای ترمِ یک است، فقط این بار روی یک ستون.

🔧 اگر کار نکرد: اولین کاری که باید بکنی print(list(df.columns)) است. در دادهٔ واقعی نامِ ستون‌ها اغلب فاصلهٔ اضافی یا حرفِ بزرگ دارند و این را با چشم نمی‌بینی. یک عادتِ خوب برای شروعِ هر پروژه: df.columns = df.columns.str.strip().str.lower().

🤖 از دستیارت بپرس: «در pandas تفاوتِ groupby().mean() و pivot_table() چیست؟ کِی کدام را به‌کار ببرم؟» جوابش را با کاری که در بخشِ ۳ و ۴ کردیم مقایسه کن — هر دو یک محاسبه بودند با دو شکلِ نمایش. اگر دستیار ادعا کرد یکی سریع‌تر یا دقیق‌تر است، خودت روی همین داده امتحانش کن.

واژه‌های تازهٔ این فصل#

کلمه تلفظ به حروف فارسی یعنی چه
groupby گروپ‌بای تقسیمِ داده به گروه و گرفتنِ یک عدد از هر گروه
agg اَگ چند تابعِ تجمیع را همزمان اعمال می‌کند
pivot_table پیوت تیبل جدولِ دوبعدی از تجمیع؛ یک متغیر در ردیف، یکی در ستون
aggfunc اَگ‌فانک تابعی که روی هر گروه اعمال می‌شود

تمرین‌ها

اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.

در فصل بعد#

عددها را داری، ولی جدولِ عدد بدترین راهِ دیدنِ یک روند است. آن نُه عددِ بخشِ ۵ را یک نمودارِ خطی در یک نگاه می‌گوید. فصلِ بعد matplotlib را می‌آورد و — مهم‌تر از دستورهایش — این سؤال را جواب می‌دهد: برای هر سؤالی که داری، کدام شکلِ نمودار درست است؟

به آخر این فصل رسیدی!

اگر ساختی و جواب داد، این دکمه مال توست.