Vaqt qatorlari: sana bilan ishlash
Sahna: "o'tgan oyga nisbatan"
Savdo — vaqt bo'ylab oqim. Eng ko'p beriladigan savollar vaqt haqida: haftalik trend qanday? Qaysi kun va soat eng band? Bu oy o'tgan oydan necha foiz yaxshi? 14-bobda oylarni dt.month bilan ajratdik. Bu bobda pandas ning vaqt asboblarini to'liq ochamiz.
import pandas as pd savdo = pd.read_csv(DATA / "dokon_savdo.csv", parse_dates=["sana"], date_format="%d.%m.%Y") savdo["tushum"] = savdo["miqdor"] * savdo["narx"] print(savdo["sana"].dtype, savdo["sana"].min().date(), "—", savdo["sana"].max().date())
datetime64[ns] 2025-01-01 — 2025-12-31
datetime64 — sana uchun maxsus tur. Matn emas: unda yil, oy, kun, hafta kuni — hammasi bor, va sanalar bilan hisoblash mumkin.
.dt: sanadan bo'laklar
s = savdo["sana"] bolaklar = pd.DataFrame({"sana": s, "oy": s.dt.month, "kun": s.dt.day, "hafta_kuni": s.dt.dayofweek, "nomi": s.dt.day_name(), "chorak": s.dt.quarter}) bolaklar.drop_duplicates("sana").iloc[[0, 40, 200]]
| sana | oy | kun | hafta_kuni | nomi | chorak | |
|---|---|---|---|---|---|---|
| 0 | 2025-01-01 00:00:00 | 1 | 1 | 2 | Wednesday | 1 |
| 851 | 2025-02-10 00:00:00 | 2 | 10 | 0 | Monday | 1 |
| 5587 | 2025-07-20 00:00:00 | 7 | 20 | 6 | Sunday | 3 |
.dt — sana ustuni uchun asboblar (.str matn uchun bo'lgani kabi). dayofweek — dushanba 0, yakshanba 6.
Sana va soatni birlashtirib, to'liq vaqt yasaymiz:
savdo["vaqt_toliq"] = pd.to_datetime(savdo["sana"].dt.strftime("%Y-%m-%d") + " " + savdo["vaqt"]) savdo["soat"] = savdo["vaqt_toliq"].dt.hour savdo[["sana", "vaqt", "vaqt_toliq", "soat"]].head(3)
| sana | vaqt | vaqt_toliq | soat | |
|---|---|---|---|---|
| 0 | 2025-01-01 00:00:00 | 10:25 | 2025-01-01 10:25:00 | 10 |
| 1 | 2025-01-01 00:00:00 | 13:37 | 2025-01-01 13:37:00 | 13 |
| 2 | 2025-01-01 00:00:00 | 13:37 | 2025-01-01 13:37:00 | 13 |
Hafta kuni va soat bo'yicha naqsh
cheklar = savdo.groupby(["chek_id", "sana", "soat"], as_index=False)["tushum"].sum() kunlar = ["Du", "Se", "Ch", "Pa", "Ju", "Sh", "Ya"] kunlik = cheklar.groupby("sana")["tushum"].sum() hafta = kunlik.groupby(kunlik.index.dayofweek).mean().div(1e6) soat = cheklar.groupby("soat").size() fig, (chap, ong) = plt.subplots(1, 2, figsize=(11, 3.2)) chap.bar(kunlar, hafta.values, color=["#a8c7fa"] * 5 + ["#1a73e8"] * 2) chap.set_title("O'rtacha kunlik tushum, mln so'm") ong.bar(soat.index, soat.values, color="#b06000") ong.set_title("Soat bo'yicha cheklar soni") ong.set_xlabel("soat") plt.show() print("dam olish / ish kuni nisbati:", round(hafta.iloc[5:].mean() / hafta.iloc[:5].mean(), 2))
dam olish / ish kuni nisbati: 1.25

Ikki xulosa: dam olish kunlari tushum ish kunlaridan taxminan to'rtdan bir ko'p; soatlar bo'yicha esa cheklar 8:00 dan 21:00 gacha tekis taqsimlangan — aniq "eng band soat" yo'q. Ikkinchi xulosa ham ma'lumot: tushlik paytiga qo'shimcha kassir qo'yish shart emasligini aytadi.
Hisobga e'tibor bering: hafta kuni o'rtachasi kunlik jamlardan olindi (avval kun bo'yicha yig'indi, keyin o'rtacha) — 14-bobdagi ikki bosqichli guruhlash qoidasi.
resample: vaqt bo'yicha guruhlash
groupby ning vaqt uchun maxsus varianti — resample. Sana index bo'lishi kerak:
kunlik = savdo.set_index("sana")["tushum"].resample("D").sum() haftalik = kunlik.resample("W").sum() oylik = kunlik.resample("ME").sum() print(len(kunlik), "kun,", len(haftalik), "hafta,", len(oylik), "oy") (oylik / 1e6).round(1).tail(3)
365 kun, 53 hafta, 12 oy
| sana | tushum |
|---|---|
| 2025-10-31 00:00:00 | 59.4 |
| 2025-11-30 00:00:00 | 52.1 |
| 2025-12-31 00:00:00 | 72.1 |
"D" — kun, "W" — hafta, "ME" — oy oxiri (month end). resample kalendar bo'yicha guruhlaydi: savdosi bo'lmagan kun ham 0 bilan qatnashadi. groupby("sana") da esa bunday kun uchun qator umuman bo'lmaydi — va kunlik o'rtacha jimgina oshib ketadi.
rolling: shovqinni silliqlash
Kunlik tushum "arra" kabi sakraydi: shanba baland, dushanba past. Trendni ko'rish uchun — sirpanuvchi o'rtacha:
silliq = kunlik.rolling(7).mean() oylik_silliq = kunlik.rolling(30).mean() fig, ax = plt.subplots(figsize=(11, 3.6)) ax.plot(kunlik.index, kunlik / 1e6, color="#dadce0", linewidth=0.8, label="kunlik") ax.plot(silliq.index, silliq / 1e6, color="#1a73e8", label="7 kunlik o'rtacha") ax.plot(oylik_silliq.index, oylik_silliq / 1e6, color="#c5221f", linewidth=2, label="30 kunlik o'rtacha") ax.axvline(pd.Timestamp("2025-10-01"), color="#137333", linestyle="--", label="5-filial ochildi") ax.set_ylabel("mln so'm") ax.legend(ncol=4, loc="upper left") plt.show()

rolling(7).mean() — har kun uchun oxirgi 7 kunning o'rtachasi: hafta ichidagi sakrash yo'qoladi, chunki har oyna har hafta kunidan bittadan oladi. Birinchi 6 kunda natija yo'q (NaN) — oyna to'lmagan. 30 kunlik chiziqda mavsum ko'rinadi: qishning boshida past, mart va yil oxirida baland. Oktyabrdan keyingi ko'tarilishning bir qismi — yangi filial (yashil chiziq): trendni talqin qilishda tarmoq kengayganini unutmang.
Oyma-oy o'zgarish: pct_change va shift
oy_mln = (oylik / 1e6).round(1) jadval = pd.DataFrame({ "tushum": oy_mln, "otgan_oy": oy_mln.shift(1), "ozgarish_%": (oylik.pct_change() * 100).round(1), }) jadval.index = jadval.index.strftime("%Y-%m") jadval
| sana | tushum | otgan_oy | ozgarish_% |
|---|---|---|---|
| 2025-01 | 29.3 | NaN | NaN |
| 2025-02 | 27.1 | 29.3 | -7.5 |
| 2025-03 | 54.5 | 27.1 | 100.6 |
| 2025-04 | 44.2 | 54.5 | -18.7 |
| 2025-05 | 42.2 | 44.2 | -4.6 |
| 2025-06 | 49.3 | 42.2 | 16.9 |
| 2025-07 | 41.8 | 49.3 | -15.4 |
| 2025-08 | 46.3 | 41.8 | 10.8 |
| 2025-09 | 45.9 | 46.3 | -0.7 |
| 2025-10 | 59.4 | 45.9 | 29.2 |
| 2025-11 | 52.1 | 59.4 | -12.2 |
| 2025-12 | 72.1 | 52.1 | 38.2 |
shift(1)— ustunni bir qadam pastga suradi: har qatorda o'tgan oyning qiymati.pct_change()—(bu oy − o'tgan oy) / o'tgan oy: oyma-oy o'sish. Birinchi oy uchun o'tgan oy yo'q —NaN.
Mart — eng katta o'sish (fevraldan keyin), aprel — pasayish. Bu raqamlarni "yaxshi/yomon oy" deb o'qishdan oldin mavsumni eslang: martning o'sishi har yili takrorlanishi mumkin. Haqiqiy taqqoslash — o'tgan yilning o'sha oyi bilan (shift(12)), lekin bunda kamida ikki yillik ma'lumot kerak.
2-qism xulosasi: pandas
| Bob | Asosiy g'oya |
|---|---|
| 8 | Series, DataFrame, index bo'yicha moslashish |
| 9 | read_csv: sana formati, sep, index=False |
| 10 | so'roq tartibi: info, describe, isna, duplicated, value_counts |
| 11 | loc / iloc, filtrlar, loc bilan yozish |
| 12 | tozalash: takror, matn, son, bo'sh katak |
| 13 | yangi ustunlar, cut, apply vs vektor, method chaining |
| 14 | groupby, agg, transform, pivot_table, ikki bosqichli guruhlash |
| 15 | merge qopqonlari: takror kalit, yo'qolgan qatorlar |
| 16 | .dt, resample, rolling, pct_change |
Butun qism bitta g'oya atrofida: har amaldan keyin tekshiring — qatorlar soni, summa, NaN lar soni. pandas xato kamdan-kam beradi; noto'g'ri, lekin chiroyli natijani esa tez-tez beradi.
Keyingi qism — Matplotlib: shu kitobda ishlatgan hamma rasmlarning ichini ochamiz va o'z grafiklaringizni hisobot sifatida tayyorlashni o'rganamiz.
Mashqlar
- Har oyning eng yaxshi kuni qaysi sana bo'lgan? (maslahat:
kunlik.groupby(kunlik.index.month).idxmax()) - To'lov turlari ulushi oyma-oy qanday o'zgargan? Har oy uchun
crosstab, keyin chiziqli grafik. rolling(7, center=True)varolling(7)farqi nima? Ikkalasini bitta grafikda chizing.
Javoblar
kunlik.groupby(kunlik.index.month).idxmax()— har oy uchun sana.pd.crosstab(savdo["sana"].dt.month, savdo["tolov"], normalize="index").plot().center=True— oyna kunning ikki tomonidan olinadi (3 kun oldin, 3 kun keyin), shuning uchun chiziq vaqt bo'yicha "kechikmaydi"; oddiyrollingfaqat o'tgan kunlarga qaraydi.
Bu bobni bepul o'qidingiz.
Kitob o'rgatadi, lekin sizning kodingiz nega ishlamaganini ayta olmaydi. Kursda uy vazifangiz tekshiriladi.