Asosiy qismga o'tish

Tozalash: iflos ma'lumotdan ishonchli jadvalga

12-bob 10 kod bloki 1683 so'z

Bu bobdagi kod shu fayllar bilan ishlaydio'z kompyuteringizda ishga tushiring

Sahna: to'rtta muammo

10-bobdagi so'roq avto_savdo.csv da to'rtta muammo topdi:

  1. 12 ta takror e'lon — hisobda ikki marta sanaladi.
  2. Model nomlari 45 xil yozilgan, aslida 9 ta model.
  3. Narx — matn, uch xil formatda: "123 500 000 so'm", "45 mln so'm", "32500000".
  4. Probeg — matn (bo'shliqli raqamlar) va 37 ta bo'sh katak.

Tozalash — tahlilning eng zerikarli va eng muhim qismi. Iflos ma'lumotdagi o'rtacha narx — chiroyli, aniq, va noto'g'ri son. Bu bobda to'rttasini tartib bilan tuzatamiz va har qadamdan keyin tekshiramiz.

python5 qator
import numpy as np
import pandas as pd

xom = pd.read_csv(DATA / "avto_savdo.csv", parse_dates=["sana"], date_format="%d.%m.%Y")
print(xom.shape)
Chiqish
(612, 9)

xom (xom ashyo) — asl jadvalga tegmaymiz, har qadam yangi jadval beradi. Xato qilsak, boshidan qaytamiz.

1. Takrorlar

python4 qator
print("takror qatorlar:", xom.duplicated().sum())
toza = xom.drop_duplicates()
print(xom.shape, "->", toza.shape)
print("elon_id endi noyobmi:", toza["elon_id"].is_unique)
Chiqish
takror qatorlar: 12
(612, 9) -> (600, 9)
elon_id endi noyobmi: True

drop_duplicates() butunlay bir xil qatorlarning birinchisini qoldiradi. Tekshiruv — is_unique: har e'lon raqami endi bir marta. Agar bir xil elon_id li, lekin boshqa narxli qatorlar bo'lganida — bu "takror" emas, "qaysi biri to'g'ri?" degan savol bo'lardi, va subset=["elon_id"] bilan ko'r-ko'rona o'chirish xato bo'lardi.

2. Matn birlashtirish

python3 qator
toza = toza.assign(model=toza["model"].str.strip().str.title())
print("modellar soni:", toza["model"].nunique())
print(sorted(toza["model"].unique()))
Chiqish
modellar soni: 9
['Captiva', 'Cobalt', 'Damas', 'Gentra', 'Malibu', 'Nexia 3', 'Onix', 'Spark', 'Tracker']

.str.strip() — boshi va oxiridagi bo'shliqlarni olib tashlaydi, .str.title() — har so'zni bosh harf bilan. 45 xil yozilish → 9 ta model. "Nexia 3" ham to'g'ri qoldi: raqamga title tegmaydi.

assign(model=...) — ustunni yangilab, yangi jadval qaytaradi (11-bobdagi loc bilan yozish asl jadvalni o'zgartiradi). Bu bobda asl xom ni saqlab qolish uchun shu usulni ishlatamiz.

Natijani rasmda solishtiramiz:

python6 qator
fig, (chap, ong) = plt.subplots(1, 2, figsize=(11, 3.4))
xom["model"].value_counts().plot(kind="bar", ax=chap, color="#c5221f", title=f"Oldin: {xom['model'].nunique()} xil")
toza["model"].value_counts().plot(kind="bar", ax=ong, color="#137333", title=f"Keyin: {toza['model'].nunique()} xil")
chap.set_xticks([])
ong.tick_params(axis="x", rotation=45)
plt.show()

Chapda — bitta model bir nechta kichik ustunlarga "sochilgan". Shunday jadval bilan "eng mashhur model" savoli noto'g'ri javob beradi: tozalashdan oldin birinchi o'rinda Onix (41 e'lon) edi, keyin esa Gentra — 80 e'lon. Gentra ning e'lonlari besh xil yozilishga bo'linib ketgan edi.

3. Narxni songa aylantirish

Narx uch formatda. Har formatni alohida qoida bilan o'qiymiz:

python9 qator
matn = toza["narx"].str.lower().str.replace("so'm", "").str.replace(" ", "")
mln = matn.str.endswith("mln")
son = pd.to_numeric(matn.str.replace("mln", ""), errors="coerce")
narx = np.where(mln, son * 1_000_000, son)

namuna = pd.DataFrame({"asl": toza["narx"], "natija": narx}).groupby(mln.to_numpy()).head(2)
print(namuna.to_string())
print("son bo'lmay qolganlar:", pd.isna(narx).sum())
toza = toza.assign(narx=narx)
Chiqish
                asl     natija
0  123 500 000 so'm  123500000
1          32500000   32500000
5      138 mln so'm  138000000
6      166 mln so'm  166000000
son bo'lmay qolganlar: 0

Qadamlar:

  1. lower(), keyin "so'm" va bo'shliqlarni olib tashlash: "123 500 000 so'm" → "123500000", "45 mln so'm" → "45mln".
  2. Qaysilari "mln" bilan tugashini eslab qolamiz — mln mask.
  3. pd.to_numeric(..., errors="coerce") — matnni songa. coerce: songa aylanmaydigan narsa bo'lsa — xato emas, NaN. Keyin ularni sanaymiz: 0 ta — hammasi aylandi.
  4. np.where (3-bob): "mln" bo'lsa million barobar, aks holda o'zi.

Oxirgi tekshiruv — "son bo'lmay qolganlar" soni. Bu qatorni hech qachon tashlab ketmang: coerce jimgina NaN qo'yadi, va siz uni sanamasangiz, yo'qolgan narxlar o'rtachani indamay buzadi.

4. Probeg: matn va bo'sh kataklar

python3 qator
probeg = pd.to_numeric(toza["probeg_km"].astype(str).str.replace(" ", ""), errors="coerce")
print("bo'sh:", probeg.isna().sum(), "| eng kam:", probeg.min(), "| eng ko'p:", probeg.max())
toza = toza.assign(probeg_km=probeg)
Chiqish
bo'sh: 37 | eng kam: 9406.0 | eng ko'p: 262668.0

Bo'shliqlarni olib tashlab, songa aylantirdik. Bo'sh kataklar NaN bo'lib qoldi — endi ular bilan nima qilish kerak?

Bo'sh katak: o'chirish, to'ldirish yoki belgilash

Uchta yo'l bor, va to'g'risi savolga bog'liq:

Usul Qachon
Qatorni o'chirish (dropna) bo'sh kataklar kam va tasodifiy; ustun tahlilda muhim
To'ldirish (fillna) modelga butun jadval kerak; yaxshi taxmin bor
Belgilash (yangi ustun) "bo'sh" ning o'zi ma'lumot bo'lishi mumkin

Probeg mashina yoshiga qattiq bog'liq. Shuning uchun umumiy o'rtacha bilan to'ldirish (5-bobdagi tuzoq) yangi mashinaga 150 ming km, eskisiga 50 ming km yozib qo'yadi. Yaxshiroq taxmin — o'sha yildagi mashinalarning mediani:

python9 qator
toza = toza.assign(probeg_bormi=toza["probeg_km"].notna())
yil_mediani = toza.groupby("yil")["probeg_km"].transform("median")
umumiy = toza["probeg_km"].median()
toza = toza.assign(probeg_km=toza["probeg_km"].fillna(yil_mediani))

misol = toza.loc[~toza["probeg_bormi"], ["yil", "probeg_km"]].sort_values("yil").iloc[[0, -1]]
print(misol.to_string())
print(f"umumiy median bilan bo'lganda hammasiga {umumiy:,.0f} km yozilardi".replace(",", " "))
print("bo'sh qoldi:", toza["probeg_km"].isna().sum())
Chiqish
      yil  probeg_km
20   2012   240300.0
601  2024    28385.0
umumiy median bilan bo'lganda hammasiga 137 188 km yozilardi
bo'sh qoldi: 0

groupby("yil")["probeg_km"].transform("median") — har qatorga o'z yilining mediani (14-bobda groupby ni batafsil ochamiz; transform — natijani har qatorga qaytaradi). Eng eski va eng yangi mashinaga qarang: ularning to'ldirilgan probegi juda farq qiladi — umumiy median bilan esa bir xil bo'lardi.

probeg_bormi ustuni — belgi: keyinchalik "taxminiy probegli mashinalar" ni alohida ko'rish yoki modelga "bu qiymat taxminiy" deb aytish mumkin. To'ldirdik, lekin unutmadik.

Natija: oldin va keyin

python1 qator
toza.info()
Chiqish
<class 'pandas.core.frame.DataFrame'>
Index: 600 entries, 0 to 611
Data columns (total 10 columns):
 #   Column        Non-Null Count  Dtype         
---  ------        --------------  -----         
 0   elon_id       600 non-null    int64         
 1   sana          600 non-null    datetime64[ns]
 2   model         600 non-null    object        
 3   rang          600 non-null    object        
 4   yil           600 non-null    int64         
 5   probeg_km     600 non-null    float64       
 6   uzatma        600 non-null    object        
 7   viloyat       600 non-null    object        
 8   narx          600 non-null    int64         
 9   probeg_bormi  600 non-null    bool          
dtypes: bool(1), datetime64[ns](1), float64(1), int64(3), object(4)
memory usage: 47.5+ KB

Hamma ustun to'g'ri turda, bo'sh katak yo'q, takror yo'q. Endi narx haqida birinchi ishonchli tahlil:

python7 qator
tartib = toza.groupby("model")["narx"].median().sort_values().index
fig, ax = plt.subplots(figsize=(10, 3.8))
ax.boxplot([toza.loc[toza["model"] == m, "narx"] / 1e6 for m in tartib], labels=tartib)
ax.set_ylabel("narx, mln so'm")
ax.set_title("Model bo'yicha narx (tozalangandan keyin)")
plt.show()
toza.groupby("model")["narx"].median().div(1e6).round(1).sort_values()
modelnarx
Spark42.8
Damas44.5
Nexia 358
Gentra79.8
Cobalt83
Onix109.2
Tracker164
Malibu180
Captiva197

Spark va Damas eng arzon, Captiva eng qimmat — kutilganidek. Har qutining ichida esa katta tarqalish: bir xil model yiliga va probegiga qarab ikki-uch barobar farq qiladi. 14-bobda shu tarqalishni yil bo'yicha ochamiz.

Toza jadvalni saqlaymiz — o'z kompyuteringizda keyingi boblarni shu fayldan boshlashingiz mumkin (kitobning o'zida esa 13-bob butun tozalashni bitta zanjirda qaytadan bajaradi):

python2 qator
toza.to_csv(ISH / "avto_toza.csv", index=False)
print(toza.shape)
Chiqish
(600, 10)

Xulosa: tozalash tartibi

  1. Asl jadvalga tegmang — xom saqlanadi, har qadam yangi jadval.
  2. Takrorlar — drop_duplicates, keyin kalit ustun is_unique mi.
  3. Matn — .str.strip(), .str.lower()/.title(); natijani nunique bilan tekshiring.
  4. Songa aylantirish — avval belgilarni olib tashlash, keyin pd.to_numeric(errors="coerce"), va albatta nechta NaN chiqqanini sanash.
  5. Bo'sh kataklar — o'chirish, to'ldirish yoki belgilash; to'ldirsangiz — guruh bo'yicha va belgi ustuni bilan.
  6. Oxirida — info() va oddiy rasm: natija mantiqqa mos keladimi.

Mashqlar

  1. xom dan faqat narxi "mln" bilan yozilgan e'lonlarni oling. Ular ichida eng qimmati qancha (so'mda)?
  2. Probegni yil mediani o'rniga model va yil bo'yicha median bilan to'ldiring (groupby(["model", "yil"])). Qaysi qatorlar baribir bo'sh qolishi mumkin va nega?
  3. rang ustunida yozilish xilma-xilligi bormi? Qanday tekshirasiz?

Javoblar

  1. xom[xom["narx"].str.contains("mln")] dan keyin yuqoridagi 4 qadam, max().
  2. Agar o'sha model-yil juftligida birorta ham ma'lum probeg bo'lmasa, median NaN — to'ldirilmaydi. Shuning uchun ikkinchi qadamda yil mediani bilan to'ldirish kerak.
  3. xom["rang"].value_counts() — 5 ta qiymat, hammasi bir xil yozilgan: bu ustun toza.

Bu bobni bepul o'qidingiz.

Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.

Telegramda yozish Narxlar