Vizualizatsiya: ma'lumotni ko'rish
Sahna: 1200 qatorni o'qib bo'lmaydi
Ma'lumot keldi. df.head() qildingiz — 5 qator ko'rdingiz. df.describe() qildingiz — raqamlar jadvali chiqdi.
Lekin savol javobsiz qoldi: bu ma'lumot qanday ko'rinishga ega?
Narxlar bir joyda to'planganmi yoki yoyilganmi? Ikki-uchta g'alati qiymat bormi? Metroga masofa narxga ta'sir qiladimi?
Jadvalga qarab bu savollarga javob berolmaysiz. Grafikka qarab — bir sekundda javob berasiz.
Bu bob protokolning 1-qadamini to'ldiradi: faylni ochdingiz, endi uni ko'ring.
Nega seaborn, matplotlib yetarli emasmi
matplotlib — poydevor, va u hamma narsani qila oladi. Lekin oddiy ish uchun ham ko'p kod yozishga majbur qiladi.
Bitta savol: "har bir tumanda o'rtacha narx qancha?"
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns sns.set_theme(style="whitegrid", font_scale=1.05) df = pd.read_csv(DATA / "uy_ijara.csv") # MATPLOTLIB usuli — qo'lda guruhlash, qo'lda joylash rasm, axes = plt.subplots(1, 2, figsize=(14, 4.8)) g = df.groupby("tuman").narx_usd.mean().sort_values() axes[0].barh(range(len(g)), g.values, color="#5f6368") axes[0].set_yticks(range(len(g))) axes[0].set_yticklabels(g.index) axes[0].set_xlabel("O'rtacha narx (USD)") axes[0].set_title("matplotlib — 6 qator kod", fontweight="bold") # SEABORN usuli — bitta qator sns.barplot(data=df, y="tuman", x="narx_usd", estimator="mean", errorbar=None, ax=axes[1], order=g.index, color="#1a73e8") axes[1].set_xlabel("O'rtacha narx (USD)") axes[1].set_title("seaborn — 1 qator kod", fontweight="bold") fig("matplotlib_vs_seaborn.png", caption="Bir xil natija. Chapda qo'lda guruhlash, o'ngda seaborn o'zi guruhlaydi.")

Bir xil natija. Chapda qo'lda guruhlash, o'ngda seaborn o'zi guruhlaydi.
Seaborn DataFrame ni tushunadi: siz ustun nomini berasiz, u guruhlash, hisoblash va chizishni o'zi qiladi.
Qoida
matplotlib — nozik sozlash uchun (o'q nomi, rang, o'lcham). seaborn — grafikni yaratish uchun.
Ikkisi birga ishlaydi: seaborn chizadi, matplotlib sozlaydi. Yuqoridagi kodda ham shunday.
Taqsimot: bitta ustun qanday ko'rinishga ega
Birinchi savol har doim shu: qiymatlar qanday yoyilgan?
rasm, axes = plt.subplots(1, 3, figsize=(15, 4.2)) sns.histplot(data=df, x="narx_usd", bins=35, kde=True, ax=axes[0], color="#1a73e8") axes[0].set_title("histplot — shakl") sns.boxplot(data=df, x="narx_usd", ax=axes[1], color="#43a047") axes[1].set_title("boxplot — median, chorak, chetlar") sns.violinplot(data=df, x="narx_usd", ax=axes[2], color="#8e24aa") axes[2].set_title("violinplot — shakl + chorak") fig("taqsimot.png", caption="Bir xil ustun, uch xil ko'rinish. histplot shaklni, boxplot chetki qiymatlarni ko'rsatadi.")

Bir xil ustun, uch xil ko'rinish. histplot shaklni, boxplot chetki qiymatlarni ko'rsatadi.
Endi eng muhim odat: grafik aytgan narsani raqam bilan tekshiring.
print(df.narx_usd.describe().round(1).to_string()) print() q1, q3 = df.narx_usd.quantile([0.25, 0.75]) iqr = q3 - q1 chet = df[(df.narx_usd < q1 - 1.5 * iqr) | (df.narx_usd > q3 + 1.5 * iqr)] print(f"Chorak oralig'i (IQR): {iqr:.0f}") print(f"Boxplot 'chet' deb ko'rsatadigan qatorlar: {len(chet)} ta ({len(chet)/len(df):.1%})")
count 1200.0 mean 776.1 std 229.5 min 225.0 25% 608.8 50% 767.5 75% 935.0 max 1515.0 Chorak oralig'i (IQR): 326 Boxplot 'chet' deb ko'rsatadigan qatorlar: 4 ta (0.3%)
Chetki qiymat (outlier) har doim xato EMAS
Boxplot nuqtalar ko'rsatdi — lekin bu "xato ma'lumot" degani emas. Toshkentda haqiqatan qimmat kvartiralar bor.
Qoida: chetki qiymatni tashlashdan oldin o'qing. Agar u haqiqiy bo'lsa, qoldiring. Agar narx = 999999 bo'lsa — bu kiritish xatosi, tashlang.
Bog'liqlik: ikki ustun orasida aloqa bormi
rasm, axes = plt.subplots(1, 2, figsize=(14, 4.8)) sns.scatterplot(data=df, x="maydon_m2", y="narx_usd", hue="mebel", alpha=.55, ax=axes[0], palette=["#c5221f", "#137333"]) axes[0].set_title("Maydon va narx (rang = mebel)") sns.scatterplot(data=df, x="metro_km", y="narx_usd", alpha=.45, ax=axes[1], color="#1a73e8") sns.regplot(data=df, x="metro_km", y="narx_usd", scatter=False, ax=axes[1], color="#c5221f") axes[1].set_title("Metroga masofa va narx (qizil chiziq = trend)") fig("boglanish.png", caption="Chapda: maydon oshsa narx oshadi. O'ngda: metro uzoqlashsa narx tushadi, lekin tarqalish katta.")

Chapda: maydon oshsa narx oshadi. O'ngda: metro uzoqlashsa narx tushadi, lekin tarqalish katta.
Grafik trend ko'rsatdi. Endi kuchini o'lchaymiz:
son_ustunlar = ["xonalar", "maydon_m2", "qavat", "qavatlar_soni", "metro_km", "mebel", "narx_usd"] korr = df[son_ustunlar].corr() print("narx_usd bilan korrelyatsiya:") print(korr["narx_usd"].drop("narx_usd").sort_values(ascending=False).round(3).to_string())
narx_usd bilan korrelyatsiya: maydon_m2 0.889 xonalar 0.869 mebel 0.206 qavatlar_soni 0.076 qavat 0.062 metro_km -0.156
rasm, ax = plt.subplots(figsize=(8.5, 6.5)) sns.heatmap(korr, annot=True, fmt=".2f", cmap="RdBu_r", center=0, square=True, linewidths=.5, ax=ax, cbar_kws={"shrink": .8}) ax.set_title("Korrelyatsiya matritsasi", fontweight="bold") fig("heatmap.png", caption="Qizil = ijobiy bog'liqlik, ko'k = salbiy. xonalar va maydon_m2 orasidagi 0.94 ga diqqat qiling.")

Qizil = ijobiy bog'liqlik, ko'k = salbiy. xonalar va maydon_m2 orasidagi 0.94 ga diqqat qiling.
Heatmap da avval DIAGONALDAN TASHQARIGA qarang
Diagonal har doim 1.00 — har bir ustun o'zi bilan to'liq bog'liq. Bu ma'lumot bermaydi.
Qiziq joy: xonalar va maydon_m2 orasida 0.94. Ular deyarli bir xil ma'lumotni aytadi (katta kvartirada ko'p xona bo'ladi).
Bu — multikollinearlik. U chiziqli modelning koeffitsiyentlarini beqaror qiladi (16-bob), lekin bashorat aniqligiga ko'pincha ta'sir qilmaydi. 41-bobda men aynan shu masalada adashganman.
Kategoriya grafiklari
rasm, axes = plt.subplots(1, 3, figsize=(16, 4.5)) sns.countplot(data=df, y="tuman", ax=axes[0], color="#5f6368", order=df.tuman.value_counts().index) axes[0].set_title("countplot — nechta e'lon") sns.boxplot(data=df, x="xonalar", y="narx_usd", ax=axes[1], hue="xonalar", legend=False, palette="Blues") axes[1].set_title("boxplot — xona soni va narx") sns.barplot(data=df, x="xonalar", y="ijaraga_berildi_30k", ax=axes[2], errorbar=("ci", 95), color="#137333") axes[2].set_ylabel("Tez ketish ulushi") axes[2].set_title("barplot — ishonch oralig'i bilan") fig("kategoriya.png", caption="countplot sonni, boxplot taqsimotni, barplot o'rtachani (ishonch oralig'i bilan) ko'rsatadi.")

countplot sonni, boxplot taqsimotni, barplot o'rtachani (ishonch oralig'i bilan) ko'rsatadi.
Uchinchi grafikdagi vertikal chiziqchalar — 95% ishonch oralig'i. Ular muhim: agar ikki ustunning chiziqchalari ustma-ust tushsa, ular orasidagi farq ishonchli emas.
print("Xona soni bo'yicha tez ketish ulushi:") g = df.groupby("xonalar").agg(soni=("ijaraga_berildi_30k", "size"), tez_ketish=("ijaraga_berildi_30k", "mean")) g["tez_ketish"] = g.tez_ketish.round(3) print(g.to_string()) print() print("DIQQAT: 5 xonali kvartiralar soni kam — ularning ulushiga ishonch past.")
Xona soni bo'yicha tez ketish ulushi:
soni tez_ketish
xonalar
1 222 0.860
2 412 0.636
3 345 0.351
4 174 0.178
5 47 0.064
DIQQAT: 5 xonali kvartiralar soni kam — ularning ulushiga ishonch past.
Kichik guruhdagi o'rtachaga ishonmang
Yuqoridagi jadvalda 5 xonali kvartiralar atigi bir necha o'nta. Ularning "tez ketish ulushi" tasodifga juda bog'liq.
Qoida: guruhdagi qatorlar sonini har doim ko'rsating. barplot chiroyli ustun chizadi, lekin u orqasida 3 qator yoki 300 qator borligini aytmaydi.
Ko'p o'lchov: hue, col, row
Seaborn ning eng kuchli tomoni — bitta qatorda uch-to'rt o'lchovni ko'rsatish.
qism = df[df.xonalar.isin([1, 2, 3])] g = sns.relplot(data=qism, x="maydon_m2", y="narx_usd", hue="mebel", col="xonalar", kind="scatter", height=3.8, aspect=1.05, alpha=.6, palette=["#c5221f", "#137333"]) g.figure.suptitle("Maydon va narx: xona soni bo'yicha ajratilgan", y=1.04, fontweight="bold") fig("relplot.png", caption="col='xonalar' uchta panel yaratdi. hue='mebel' rang bilan to'rtinchi o'lchovni qo'shdi.")

col='xonalar' uchta panel yaratdi. hue='mebel' rang bilan to'rtinchi o'lchovni qo'shdi.
Bitta grafikda to'rt o'lchov: maydon (x), narx (y), mebel (rang), xona soni (panel).
Qaysi grafik qachon
show(pd.DataFrame([ {"Savol": "Bitta son ustuni qanday taqsimlangan?", "Grafik": "histplot", "Qo'shimcha": "kde=True shaklni silliqlaydi"}, {"Savol": "Chetki qiymatlar bormi?", "Grafik": "boxplot", "Qo'shimcha": "Nuqtalar = IQR dan tashqarida"}, {"Savol": "Ikki son orasida aloqa bormi?", "Grafik": "scatterplot", "Qo'shimcha": "regplot trend chizig'ini qo'shadi"}, {"Savol": "Hamma son ustunlari o'zaro?", "Grafik": "heatmap(corr)", "Qo'shimcha": "yoki pairplot (sekin)"}, {"Savol": "Kategoriyada nechta qator?", "Grafik": "countplot", "Qo'shimcha": "order= bilan saralang"}, {"Savol": "Kategoriya bo'yicha o'rtacha?", "Grafik": "barplot", "Qo'shimcha": "errorbar ni O'CHIRMANG"}, {"Savol": "Kategoriya bo'yicha taqsimot?", "Grafik": "boxplot / violinplot", "Qo'shimcha": "barplot dan ko'proq ma'lumot beradi"}, {"Savol": "Vaqt bo'yicha o'zgarish?", "Grafik": "lineplot", "Qo'shimcha": "x o'qi sana bo'lishi kerak"}, {"Savol": "Uch-to'rt o'lchov birga?", "Grafik": "relplot / catplot", "Qo'shimcha": "hue, col, row"}, ]))
| Savol | Grafik | Qo'shimcha |
|---|---|---|
| Bitta son ustuni qanday taqsimlangan? | histplot | kde=True shaklni silliqlaydi |
| Chetki qiymatlar bormi? | boxplot | Nuqtalar = IQR dan tashqarida |
| Ikki son orasida aloqa bormi? | scatterplot | regplot trend chizig'ini qo'shadi |
| Hamma son ustunlari o'zaro? | heatmap(corr) | yoki pairplot (sekin) |
| Kategoriyada nechta qator? | countplot | order= bilan saralang |
| Kategoriya bo'yicha o'rtacha? | barplot | errorbar ni O'CHIRMANG |
| Kategoriya bo'yicha taqsimot? | boxplot / violinplot | barplot dan ko'proq ma'lumot beradi |
| Vaqt bo'yicha o'zgarish? | lineplot | x o'qi sana bo'lishi kerak |
| Uch-to'rt o'lchov birga? | relplot / catplot | hue, col, row |
ML uchun eng muhim grafik: target bo'yicha ajratish
Modelga o'tishdan oldin bitta grafik chizing: har bir xususiyat target ni ajratadimi?
rasm, axes = plt.subplots(1, 4, figsize=(17, 4)) for ax, u in zip(axes, ["maydon_m2", "metro_km", "narx_usd", "qavat"]): sns.boxplot(data=df, x="ijaraga_berildi_30k", y=u, ax=ax, hue="ijaraga_berildi_30k", legend=False, palette=["#c5221f", "#137333"]) ax.set_xlabel("0 = sekin ketdi 1 = tez ketdi") ax.set_title(u) fig("target_ajratish.png", caption="Qutilar bir-biridan qanchalik ajralgan bo'lsa, o'sha xususiyat shunchalik foydali.")

Qutilar bir-biridan qanchalik ajralgan bo'lsa, o'sha xususiyat shunchalik foydali.
print("Har bir xususiyat target ni qanchalik ajratadi:") qatorlar = [] for u in ["maydon_m2", "metro_km", "narx_usd", "qavat", "xonalar", "mebel"]: a = df[df.ijaraga_berildi_30k == 0][u].mean() b = df[df.ijaraga_berildi_30k == 1][u].mean() birlashgan_std = df[u].std() qatorlar.append({"Ustun": u, "Sekin o'rtacha": round(a, 2), "Tez o'rtacha": round(b, 2), "Ajratish kuchi": round(abs(b - a) / birlashgan_std, 3)}) show(pd.DataFrame(qatorlar).sort_values("Ajratish kuchi", ascending=False))
Har bir xususiyat target ni qanchalik ajratadi:
| Ustun | Sekin o'rtacha | Tez o'rtacha | Ajratish kuchi |
|---|---|---|---|
| narx_usd | 894.46 | 660.86 | 1.018 |
| maydon_m2 | 67.22 | 47.41 | 0.983 |
| xonalar | 3.03 | 2 | 0.963 |
| qavat | 4.99 | 5.21 | 0.06 |
| metro_km | 2.62 | 2.55 | 0.048 |
| mebel | 0.61 | 0.62 | 0.018 |
Oxirgi ustun — standart og'ishga normallashtirilgan farq. U qanchalik katta bo'lsa, xususiyat shunchalik foydali.
E'tibor bering: narx_usd eng kuchli ajratadi. Mantiqan to'g'ri — arzon kvartira tezroq ketadi. Lekin biz uni xususiyat sifatida ishlatmaymiz, chunki u ikkinchi target (0-bob, 7-qadam).
Hisobot uchun sozlash
sns.set_theme(style="whitegrid", font_scale=1.1) rasm, ax = plt.subplots(figsize=(10, 5)) g = df.groupby("tuman").agg(ortacha=("narx_usd", "mean"), soni=("narx_usd", "size")).sort_values("ortacha") sns.barplot(x=g.ortacha, y=g.index, ax=ax, color="#1a73e8") for i, (v, n) in enumerate(zip(g.ortacha, g.soni)): ax.text(v + 8, i, f"{v:.0f} USD (n={n})", va="center", fontsize=9.5, color="#333") ax.set_xlabel("O'rtacha ijara narxi, USD/oy") ax.set_ylabel("") ax.set_title("Toshkent tumanlari bo'yicha o'rtacha ijara narxi", fontweight="bold", pad=14) ax.set_xlim(0, g.ortacha.max() * 1.28) sns.despine(left=True, bottom=True) fig("hisobot.png", caption="Hisobotga tayyor grafik: qiymat yozilgan, guruh hajmi (n) ko'rsatilgan, chiziqlar olib tashlangan.")

Hisobotga tayyor grafik: qiymat yozilgan, guruh hajmi (n) ko'rsatilgan, chiziqlar olib tashlangan.
Hisobot grafigining uch qoidasi: qiymatni yozing, guruh hajmini ko'rsating (n=), keraksiz chiziqlarni olib tashlang.
Bugun nima o'rgandik
show(pd.DataFrame([ {"Qoida": "Avval ko'r, keyin model qur", "Nega": "Grafik bir sekundda jadvaldan ko'proq aytadi"}, {"Qoida": "seaborn — DataFrame tilida", "Nega": "Ustun nomini berasiz, u guruhlaydi va chizadi"}, {"Qoida": "Grafikni RAQAM bilan tekshir", "Nega": "Ko'z aldaydi; describe() va corr() tasdiqlaydi"}, {"Qoida": "Guruh hajmini ko'rsat", "Nega": "3 qatorli guruh o'rtachasi ma'nosiz"}, {"Qoida": "errorbar ni o'chirma", "Nega": "Ustma-ust tushgan oraliq = farq ishonchli emas"}, {"Qoida": "Chetki qiymatni o'qib tashla", "Nega": "Hammasi xato emas — ba'zilari haqiqat"}, {"Qoida": "Target bo'yicha ajratib ko'r", "Nega": "Qaysi xususiyat foydali ekanini oldindan ko'rsatadi"}, ]))
| Qoida | Nega |
|---|---|
| Avval ko'r, keyin model qur | Grafik bir sekundda jadvaldan ko'proq aytadi |
| seaborn — DataFrame tilida | Ustun nomini berasiz, u guruhlaydi va chizadi |
| Grafikni RAQAM bilan tekshir | Ko'z aldaydi; describe() va corr() tasdiqlaydi |
| Guruh hajmini ko'rsat | 3 qatorli guruh o'rtachasi ma'nosiz |
| errorbar ni o'chirma | Ustma-ust tushgan oraliq = farq ishonchli emas |
| Chetki qiymatni o'qib tashla | Hammasi xato emas — ba'zilari haqiqat |
| Target bo'yicha ajratib ko'r | Qaysi xususiyat foydali ekanini oldindan ko'rsatadi |
Keyingi bobda: ma'lumotni ko'rdik, muammolarni topdik. Endi ularni tuzatamiz — model qabul qiladigan shaklga keltiramiz.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.