Asosiy qismga o'tish

Vaqt qatorlari: sana bilan ishlash

16-bob 7 kod bloki 1443 so'z

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

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.

python5 qator
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())
Chiqish
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

python4 qator
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]]
sanaoykunhafta_kuninomichorak
02025-01-01 00:00:00112Wednesday1
8512025-02-10 00:00:002100Monday1
55872025-07-20 00:00:007206Sunday3

.dt — sana ustuni uchun asboblar (.str matn uchun bo'lgani kabi). dayofweek — dushanba 0, yakshanba 6.

Sana va soatni birlashtirib, to'liq vaqt yasaymiz:

python3 qator
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)
sanavaqtvaqt_toliqsoat
02025-01-01 00:00:0010:252025-01-01 10:25:0010
12025-01-01 00:00:0013:372025-01-01 13:37:0013
22025-01-01 00:00:0013:372025-01-01 13:37:0013

Hafta kuni va soat bo'yicha naqsh

python14 qator
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))
Chiqish
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:

python5 qator
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)
Chiqish
365 kun, 53 hafta, 12 oy
sanatushum
2025-10-31 00:00:0059.4
2025-11-30 00:00:0052.1
2025-12-31 00:00:0072.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:

python11 qator
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

python8 qator
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
sanatushumotgan_oyozgarish_%
2025-0129.3NaNNaN
2025-0227.129.3-7.5
2025-0354.527.1100.6
2025-0444.254.5-18.7
2025-0542.244.2-4.6
2025-0649.342.216.9
2025-0741.849.3-15.4
2025-0846.341.810.8
2025-0945.946.3-0.7
2025-1059.445.929.2
2025-1152.159.4-12.2
2025-1272.152.138.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

  1. Har oyning eng yaxshi kuni qaysi sana bo'lgan? (maslahat: kunlik.groupby(kunlik.index.month).idxmax())
  2. To'lov turlari ulushi oyma-oy qanday o'zgargan? Har oy uchun crosstab, keyin chiziqli grafik.
  3. rolling(7, center=True) va rolling(7) farqi nima? Ikkalasini bitta grafikda chizing.

Javoblar

  1. kunlik.groupby(kunlik.index.month).idxmax() — har oy uchun sana.
  2. pd.crosstab(savdo["sana"].dt.month, savdo["tolov"], normalize="index").plot().
  3. center=True — oyna kunning ikki tomonidan olinadi (3 kun oldin, 3 kun keyin), shuning uchun chiziq vaqt bo'yicha "kechikmaydi"; oddiy rolling faqat o'tgan kunlarga qaraydi.

Bu bobni bepul o'qidingiz.

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

Telegramda yozish Narxlar