Asosiy qismga o'tish

Aggregatsiya va axis: ko'p sondan bitta javob

5-bob 9 kod bloki 1612 so'z

Sahna: "o'rtacha qancha?"

Rahbar so'raydi: "Filiallar o'rtacha qancha sotyapti?" Bu bitta savolga o'xshaydi, aslida uchta: hamma filial va hamma kun bo'yicha bitta son mi? Har filial uchun alohida mi? Har kun uchun alohida mi? NumPy da bu farq bitta argument — axis.

Aggregatsiya — ko'p sonni bitta songa "yig'ish": yig'indi, o'rtacha, eng katta, tarqalish.

python6 qator
import numpy as np

rng = np.random.default_rng(3)
savdo = rng.integers(30, 90, size=(4, 7))
print(savdo)
print("jami:", savdo.sum(), "| o'rtacha:", savdo.mean().round(2), "| eng katta:", savdo.max())
Chiqish
[[78 35 40 44 40 78 82]
 [64 32 35 49 55 67 58]
 [45 39 71 74 31 36 57]
 [53 83 61 55 55 69 65]]
jami: 1551 | o'rtacha: 55.39 | eng katta: 83

axis berilmasa — butun array bitta son bo'ladi.

axis: qaysi o'q yo'qoladi

axis=0 qatorlar bo'ylab yig'adi, axis=1 ustunlar bo'ylab

axis=0 qatorlar bo'ylab yig'adi, axis=1 ustunlar bo'ylab

python3 qator
print("har kun (axis=0):    ", savdo.sum(axis=0))
print("har filial (axis=1): ", savdo.sum(axis=1))
print(savdo.shape, "->", savdo.sum(axis=0).shape, "va", savdo.sum(axis=1).shape)
Chiqish
har kun (axis=0):     [240 189 207 222 181 250 262]
har filial (axis=1):  [397 360 353 441]
(4, 7) -> (7,) va (4,)

Eslash usuli: axis — yig'ilib, yo'qoladigan o'q. (4, 7) da axis=0 (4 ta filial) yo'qoladi — har kun uchun bitta son qoladi, shakl (7,). axis=1 (7 kun) yo'qoladi — har filial uchun bitta son, (4,).

Ko'p o'quvchi teskari o'ylaydi: "axis=0 — qatorlar, demak har qator yig'indisi". Yo'q: axis=0 — qatorlar bo'ylab harakat, ya'ni qatorlar bir-biri bilan qo'shiladi.

Asosiy funksiyalar

python6 qator
haftalik = savdo.sum(axis=1)
print("o'rtacha:", savdo.mean(axis=1).round(1))
print("median:  ", np.median(savdo, axis=1))
print("eng kam: ", savdo.min(axis=1), " eng ko'p:", savdo.max(axis=1))
print("std:     ", savdo.std(axis=1).round(1))
print("25% va 75%:", np.percentile(savdo, [25, 75]))
Chiqish
o'rtacha: [56.7 51.4 50.4 63. ]
median:   [44. 55. 45. 61.]
eng kam:  [35 32 31 53]  eng ko'p: [82 67 74 83]
std:      [19.8 12.6 15.9  9.8]
25% va 75%: [40.  67.5]
  • mean — o'rtacha, median — saralangandagi o'rtadagi qiymat.
  • std (standart og'ish) — qiymatlar o'rtachadan odatda qancha uzoqda. Katta std — barqaror emas.
  • percentile — "qiymatlarning necha foizi shundan past": 25% va 75% — o'rtadagi yarmining chegaralari.

O'rtacha va median: bitta katta son hammasini buzadi

python11 qator
oylik = np.array([4.2, 4.5, 5.0, 5.1, 5.5, 6.0, 6.3, 7.0, 7.4, 85.0])
print(f"o'rtacha: {oylik.mean():.2f} mln, median: {np.median(oylik):.2f} mln")

fig, ax = plt.subplots(figsize=(9, 2.8))
ax.scatter(oylik, np.zeros_like(oylik), s=60, color="#5f6368", zorder=3)
ax.axvline(oylik.mean(), color="#c5221f", linewidth=2, label=f"o'rtacha {oylik.mean():.1f}")
ax.axvline(np.median(oylik), color="#137333", linewidth=2, label=f"median {np.median(oylik):.2f}")
ax.set_yticks([])
ax.set_xlabel("oylik maosh, mln so'm (10 xodim, biri — direktor)")
ax.legend()
plt.show()
Chiqish
o'rtacha: 13.60 mln, median: 5.75 mln

10 kishilik jamoada bitta direktor 85 mln oladi. O'rtacha 13.6 mln chiqdi — jamoaning hech kimi bunday olmaydi. Median esa 5.75 — odatiy xodimning maoshi. Qoida: taqsimot qiyshiq (narx, maosh, savdo) yoki chetki qiymatlar bor bo'lsa — median ni ham ko'rsating.

keepdims: natijani qaytadan qo'llash

Har kunning o'z filiali haftalik savdosidagi ulushi kerak. Buning uchun (4, 7) ni (4,) ga bo'lish kerak — lekin 4-bobdagi qoida bo'yicha bu ishlamaydi (7 va 4 mos emas).

python4 qator
ulush = savdo / savdo.sum(axis=1, keepdims=True)
print(savdo.sum(axis=1, keepdims=True).shape)
print((ulush * 100).round(1)[0])
print("har qator ulushi yig'indisi:", ulush.sum(axis=1).round(6))
Chiqish
(4, 1)
[19.6  8.8 10.1 11.1 10.1 19.6 20.7]
har qator ulushi yig'indisi: [1. 1. 1. 1.]

keepdims=True yo'qolgan o'qni 1 o'lcham bilan saqlab qoladi: (4,) emas, (4, 1). Endi broadcasting uni har ustunga to'g'ri yoyadi. Har qatordagi ulushlar yig'indisi 1 — tekshiruv shu.

Qayerda: argmax va argmin

Eng katta qiymat emas, qaysi o'rinda ekani kerak bo'lsa:

python5 qator
kunlar = np.array(["Du", "Se", "Ch", "Pa", "Ju", "Sh", "Ya"])
filiallar = np.array(["Chilonzor", "Yunusobod", "Sergeli", "Olmazor"])
print("har filialning eng yaxshi kuni:", kunlar[savdo.argmax(axis=1)])
print("har kunning eng kuchli filiali:", filiallar[savdo.argmax(axis=0)])
print("eng yomon filial (hafta bo'yicha):", filiallar[savdo.sum(axis=1).argmin()])
Chiqish
har filialning eng yaxshi kuni: ['Ya' 'Sh' 'Pa' 'Se']
har kunning eng kuchli filiali: ['Chilonzor' 'Olmazor' 'Sergeli' 'Sergeli' 'Yunusobod' 'Chilonzor'
 'Chilonzor']
eng yomon filial (hafta bo'yicha): Sergeli

Teng qiymatlar bo'lsa argmax birinchisini qaytaradi.

Yig'ilib boruvchi: cumsum va diff

python12 qator
kunlik = savdo.sum(axis=0)
jamlangan = kunlik.cumsum()
print("kunlik:     ", kunlik)
print("jamlangan:  ", jamlangan)
print("kecha bilan farq:", np.diff(kunlik))

fig, ax = plt.subplots(figsize=(8, 3))
ax.bar(kunlar, kunlik, color="#a8c7fa", label="kunlik")
ax.plot(kunlar, jamlangan, marker="o", color="#1a73e8", label="jamlangan")
ax.set_ylabel("mln so'm")
ax.legend()
plt.show()
Chiqish
kunlik:      [240 189 207 222 181 250 262]
jamlangan:   [ 240  429  636  858 1039 1289 1551]
kecha bilan farq: [-51  18  15 -41  69  12]

cumsum — har qadamda shu paytgacha jami: oy boshidan beri tushum. np.diff — qo'shni elementlar farqi: o'sish yoki pasayish. diff natijasi bitta qisqa: 7 kun — 6 ta farq.

NaN: bitta bo'sh katak hammasini yutadi

python3 qator
yozuv = np.array([12.0, np.nan, 15.0, 9.0])
print(yozuv.sum(), yozuv.mean())
print(np.nansum(yozuv), np.nanmean(yozuv), "| bo'sh emaslar:", (~np.isnan(yozuv)).sum())
Chiqish
nan nan
36.0 12.0 | bo'sh emaslar: 3

Oddiy sum va mean da bitta nan natijani nan qiladi. np.nansum, np.nanmean, np.nanmax — nan ni tashlab hisoblaydi. Lekin o'ylang: tashlash to'g'rimi? Bo'sh katak "savdo bo'lmadi" (0) bo'lsa, tashlash o'rtachani ko'tarib yuboradi. Bu — ma'lumot haqidagi qaror, kod emas. pandas bobida (12-bob) shu qarorni batafsil ko'ramiz.

Tuzoq: std da ddof

python3 qator
x = np.array([2, 4, 4, 4, 5, 5, 7, 9])
print("np.std (ddof=0):", x.std())
print("np.std(ddof=1): ", x.std(ddof=1).round(4))
Chiqish
np.std (ddof=0): 2.0
np.std(ddof=1):  2.1381

Bir xil sonlar — ikki xil standart og'ish. ddof=0 — "bu butun to'plam" (populyatsiya), ddof=1 — "bu kattaroq to'plamdan tanlangan namuna": bo'luvchi n emas, n − 1. NumPy standartda ddof=0, pandas esa ddof=1 ishlatadi. Bir xil ustunning std i NumPy va pandas da farq qilsa — sabab shu. Kichik ma'lumotda farq sezilarli, million qatorda deyarli yo'q.

Xulosa

  • Aggregatsiya: sum, mean, median, min/max, std, percentile.
  • axis — yo'qoladigan o'q: axis=0 — har ustun bitta son, axis=1 — har qator bitta son.
  • Chetki qiymat o'rtachani buzadi — median ni ham ko'rsating.
  • keepdims=True — natijani asl jadvalga broadcasting bilan qaytarish uchun.
  • argmax/argmin — qayerda; cumsum — yig'ilib boruvchi; diff — farq.
  • nan oddiy aggregatsiyani buzadi; nan-funksiyalar uni tashlaydi — bu qaror.
  • std: NumPy ddof=0, pandas ddof=1.

Mashqlar

  1. savdo dagi har kun uchun filiallar o'rtachasini va eng past filialni toping.
  2. Har filial savdosini o'sha filialning haftalik eng yaxshi kuniga nisbatan foizda ifodalang.
  3. oylik dan direktorni olib tashlasangiz, o'rtacha va median qanchaga o'zgaradi?
  4. np.array([1.0, np.nan, 3.0]).max() va np.nanmax(...) nima qaytaradi?

Javoblar

  1. savdo.mean(axis=0) va filiallar[savdo.argmin(axis=0)].
  2. (savdo / savdo.max(axis=1, keepdims=True) * 100).round().
  3. O'rtacha 13.6 dan 5.7 ga tushadi, median 5.75 dan 5.5 ga — median deyarli o'zgarmaydi.
  4. nan va 3.0.

Bu bobni bepul o'qidingiz.

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

Telegramda yozish Narxlar