در این فصل چه یاد میگیری#
جدول را خواندی و میدانی داخلش چیست. حالا باید بتوانی از آن چیزی بیرون بکشی: یک ستونِ خاص، ردیفهایی که شرطی دارند، مرتبشده بر اساسِ چیزی که برایت مهم است. در این فصل سه ابزارِ انتخاب را یاد میگیری، ماسکِ شرطیِ فصلِ ۲ را روی یک جدولِ واقعی بهکار میبری، و ستونِ محاسبهشدهٔ خودت را میسازی. اینها را در هر پروژهٔ دادهای که تا آخرِ عمر بنویسی، روزی ده بار بهکار میبری.

آخر این فصل میتوانی:
- با
locوilocبه هر ردیف و ستونی که بخواهی برسی و تفاوتشان را بگویی - با ماسکِ شرطی ردیفها را فیلتر کنی و چند شرط را ترکیب کنی
- جدول را بر اساسِ یک ستون مرتب کنی
- ستونِ محاسبهشدهٔ تازه بسازی
قبل از شروع#
از فصل ۲: ماسکِ شرطی، و اینکه ترکیبِ شرطها با & و | نوشته میشود نه and و or.
از فصل ۳: df["col"] یک Series میدهد و df[["a", "b"]] یک DataFrame.
سلولِ راهاندازی: همان laptops.csv فصلِ قبل. سلولِ بالای نوتبوک دوباره میسازدش.
📓 نوتبوک: نوتبوک این فصل را در Colab باز کن — همهٔ کدهای این فصل آماده و بهترتیب داخلش هست.
۱. loc و iloc: دو راهِ متفاوتِ اشارهکردن#
import pandas as pd
df = pd.read_csv("laptops.csv")
print(df.loc[0, "brand"])
print(df.iloc[0, 0])
print(df.loc[2:4, ["brand", "year"]])
اپل
اپل
brand year
2 اپل 2024
3 ایسوس 2023
4 لنوو 2019
هر دو خطِ اول یک چیز دادند، ولی از دو راهِ کاملاً متفاوت:
locبا برچسب کار میکند: برچسبِ ردیف (اندیس) و نامِ ستون.ilocبا شمارهٔ جایگاه کار میکند: ردیفِ چندم، ستونِ چندم — دقیقاً مثلِ آرایهٔnumpy.
اینجا هر دو یک جواب دادند فقط به این دلیل که اندیسِ ما اعدادِ ۰ تا ۲۴۳ است. بهمحضِ اینکه فیلتر کنی یا مرتب کنی، اندیس دیگر با جایگاه یکی نیست و این دو از هم جدا میشوند.
⚠️ مواظب باش: یک تفاوتِ ظریف که یک بار همه را میگیرد:
df.loc[2:4]سه ردیف داد — ۲ و ۳ و ۴. برخلافِ برشِ پایتون و برخلافِiloc،locانتهای بازه را شامل میشود، چون با برچسب کار میکند نه با جایگاه.df.iloc[2:4]فقط دو ردیف میدهد.
قبل از ادامه، جواب بده: جدولی را بر اساسِ قیمت مرتب کردهای و ردیفِ اولِ نتیجه اندیسِ ۱۹۷ دارد. برای گرفتنِ آن ردیف، df.loc[0] را بهکار ببری یا df.iloc[0]؟ جواب: iloc[0]. loc[0] سراغِ ردیفی میرود که برچسبش صفر است، که حالا جای دیگری در جدول است. این تفاوت بعد از هر مرتبسازی و هر فیلتری اهمیت پیدا میکند.
۲. فیلتر: همان ماسکِ فصلِ ۲#
recent = df[df["year"] >= 2023]
print(recent.shape)
print(recent["brand"].value_counts().head(3))
(55, 5)
brand
ایسوس 18
لنوو 14
اچ پی 8
Name: count, dtype: int64
df["year"] >= 2023 یک Series از True/False میدهد — همان ماسک. گذاشتنش داخلِ کروشهٔ df یعنی «فقط ردیفهایی که True شدند».
از ۲۴۴ ردیف، ۵۵ تا ماندند. عادت کن بعد از هر فیلتر shape را چاپ کنی: اگر عددی که میگیری خیلی بزرگتر یا کوچکتر از انتظارت است، شرطت همانی نیست که فکر میکردی.
ترکیبِ شرطها دقیقاً مثلِ numpy است:
selected = df[(df["year"] >= 2022) & (df["ram_gb"] >= 16)]
print(selected.shape)
(29, 5)
✅ چک کن: ۲۹ ردیف. اگر عددِ خیلی بزرگتری گرفتی، احتمالاً پرانتزها را جا انداختهای. اگر خطا گرفتی، بخشِ ۵ همین فصل را ببین.
۳. مرتبسازی#
newest = df.sort_values("year", ascending=False)
print(newest.head(3)[["brand", "year"]])
brand year
7 لنوو 2205
2 اپل 2024
39 لنوو 2024
sort_values جدولِ مرتبشده را برمیگرداند و اصل را دستنخورده میگذارد — پس باید نتیجه را در متغیری بگیری، وگرنه کاری نکردهای.
به اندیسها نگاه کن: 7، 2، 39. ردیفها جابهجا شدند ولی برچسبشان با خودشان آمد. این دقیقاً همان چیزی است که بخشِ ۱ دربارهٔ loc و iloc میگفت.
و به ردیفِ اول نگاه کن: سالِ ۲۲۰۵. همان مقدارِ غیرممکنی که در فصلِ ۳ در describe() دیدیم، حالا در صدرِ فهرستِ «جدیدترینها» نشسته است.
📏 اندازه بگیر: این یک درسِ کوچک ولی مهم است: مرتبسازی، مقدارهای خراب را به بالای فهرست میآورد. پس هر بار که چیزی را مرتب کردی، اولین و آخرین چند ردیف را نگاه کن — نه برای نتیجهگیری، بلکه برای پیدا کردنِ خرابی. این ارزانترین بازرسیِ داده است که میشناسیم.
۴. ستونِ تازه#
df["ram_mb"] = df["ram_gb"] * 1024
df["is_recent"] = df["year"] >= 2022
print(df[["ram_gb", "ram_mb", "is_recent"]].head(3))
print(df["is_recent"].mean().round(3))
ram_gb ram_mb is_recent
0 32.0 32768.0 False
1 16.0 16384.0 False
2 8.0 8192.0 True
0.311
ساختنِ ستونِ تازه دقیقاً مثلِ گذاشتنِ کلیدِ تازه در یک dict است: df["نام تازه"] = مقدار. و چون عملیات برداری است، یک خط کافی است — بدونِ حلقه، برای هر ۲۴۴ ردیف.
آن mean() روی ستونِ True/False همان ترفندِ فصلِ ۲ است: ۳۱٫۱ درصد از آگهیها مربوط به سالِ ۲۰۲۲ به بعدند.
💡 نکته: به
.round(3)دقت کن. بدونِ آن عددِ0.3110655737704918را میگرفتی — شانزده رقمِ اعشار برای یک درصد. عادت کن هر عددی که قرار است خوانده شود را گِرد کنی. این نه تزئین است و نه بیدقتی؛ نشاندادنِ دقتی که وجود ندارد، خودش یک نوع بیدقتی است.
۵. یک خطای واقعی: پرانتزهای جامانده#
df[df["year"] >= 2022 & df["ram_gb"] >= 16]
TypeError: Cannot perform 'rand_' with a dtyped [float64] array and scalar of type [bool]
پیام گیجکننده است چون از لایههای درونیِ pandas میآید، ولی علتش ساده است: عملگرِ & تقدمِ بالاتری از >= دارد، پس پایتون اول 2022 & df["ram_gb"] را حساب میکند — یعنی «و»ی منطقیِ یک عدد با یک ستونِ اعشاری، که بیمعناست.
راهِ رفعش همان چیزی است که در بخشِ ۲ نوشتیم: هر شرط را داخلِ پرانتزِ خودش بگذار.
🔧 اگر کار نکرد: اگر بهجای این، پیامِ
ValueError: The truth value of a Series is ambiguousگرفتی، یعنیandنوشتهای بهجای&. هر دو خطا یک ریشه دارند و یک راهِ حل:&و|و~، هر کدام با پرانتزِ خودشان.
🤖 از دستیارت بپرس: «در pandas تفاوتِ
locوilocچیست؟ یک مثال بزن که در آن نتیجهشان متفاوت باشد.» تأکید روی «متفاوت» عمدی است: مثالی که هر دو یک جواب میدهند چیزی یاد نمیدهد. جوابش را در نوتبوک اجرا کن و ببین واقعاً متفاوت شد یا نه.
واژههای تازهٔ این فصل#
| کلمه | تلفظ به حروف فارسی | یعنی چه |
|---|---|---|
| loc | لوک | انتخاب با برچسب؛ انتهای بازه را شامل میشود |
| iloc | آیلوک | انتخاب با شمارهٔ جایگاه؛ مثلِ برشِ پایتون |
| sort_values | سورت ولیوز | جدولِ مرتبشده را برمیگرداند، اصل را عوض نمیکند |
تمرینها
اول خودت فکر کن یا امتحان کن — بعد اینجا را باز کن.
در فصل بعد#
تا اینجا چهار مشکل در داده پیدا کردهای و از کنارِ همهشان رد شدهای: قیمتِ متنی، خانههای خالی، سالِ غیرممکن، و برندی که به دو شکل نوشته شده. تمرینِ ستارهدار پنجمی را هم نشانت داد. فصلِ بعد یک فصلِ ⚠️ است و کاملاً به همین اختصاص دارد — دادهٔ کثیف — و آنجاست که کارِ واقعیِ علمِ داده شروع میشود. مهمتر از تکنیکها، یک چیز را یاد میگیری: هر تصمیمِ پاکسازی، یک تصمیم دربارهٔ معنای داده است، نه یک کارِ فنی.
به آخر این فصل رسیدی!
اگر ساختی و جواب داد، این دکمه مال توست.