Asosiy qismga o'tish

Indexing va slicing: kerakli bo'lakni olish

3-bob 9 kod bloki 1454 so'z

Sahna: haftalik savdo jadvali

Do'kon tarmog'ida 4 filial, har biri uchun 7 kunlik savdo (million so'mda). Savollar har kuni boshqa: "2-filialning shanba kungi savdosi?", "hamma filialning dushanbasi?", "50 dan past kunlar qaysi?". Har savol — jadvaldan bitta bo'lak olish. Bu bobning ishi shu.

python8 qator
import numpy as np

rng = np.random.default_rng(3)
kunlar = np.array(["Du", "Se", "Ch", "Pa", "Ju", "Sh", "Ya"])
filiallar = np.array(["Chilonzor", "Yunusobod", "Sergeli", "Olmazor"])
savdo = rng.integers(30, 90, size=(4, 7))
print(savdo)
print(savdo.shape)
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]]
(4, 7)

Qatorlar — filiallar (axis 0), ustunlar — kunlar (axis 1).

Bitta element va bitta qator

python3 qator
print(savdo[1, 5])
print(savdo[1])
print(savdo[-1, -1])
Chiqish
67
[64 32 35 49 55 67 58]
65
  • savdo[1, 5] — 1-qator, 5-ustun: Yunusobod, shanba. Indeks 0 dan boshlanadi: 0-qator — Chilonzor.
  • savdo[1] — butun 1-qator: Yunusobod ning haftasi.
  • -1 — oxiridan birinchi: oxirgi filial, oxirgi kun. Uzunlikni bilmasangiz ham oxirgisini olasiz.

savdo[1][5] ham ishlaydi, lekin u ikki qadam: avval qator nusxasini yasaydi, keyin undan oladi. savdo[1, 5] — bitta qadam va har doim to'g'ri usul.

Slicing: oraliq olish

Qaysi kataklar tanlanadi: a[1], a[:, 2], a[0:2, 1:3], a[::2, ::2]

Qaysi kataklar tanlanadi: a[1], a[:, 2], a[0:2, 1:3], a[::2, ::2]

Qoida Python ro'yxatidagi bilan bir xil — start:stop:step, stop kirmaydi — faqat har o'q uchun alohida, vergul bilan:

python4 qator
print("dushanba, hamma filial:", savdo[:, 0])
print("Chilonzor, ish kunlari:", savdo[0, :5])
print("dam olish kunlari:\n", savdo[:, 5:])
print("har ikkinchi kun:", kunlar[::2])
Chiqish
dushanba, hamma filial: [78 64 45 53]
Chilonzor, ish kunlari: [78 35 40 44 40]
dam olish kunlari:
 [[78 82]
 [67 58]
 [36 57]
 [69 65]]
har ikkinchi kun: ['Du' 'Ch' 'Ju' 'Ya']

: yolg'iz — "shu o'q bo'yicha hammasi". savdo[:, 0] — barcha qatorlar, 0-ustun. 5: — 5 dan oxirigacha.

View va copy: eng xavfli farq

Slicing ma'lumotni ko'chirmaydi. U asl array ga boshqa "deraza" ochadi — view. Derazadan o'zgartirsangiz, asl ham o'zgaradi.

Slice view beradi va asl o'zgaradi; ro'yxat bilan indekslash copy beradi

Slice view beradi va asl o'zgaradi; ro'yxat bilan indekslash copy beradi

python12 qator
a = np.array([10, 20, 30, 40, 50])
b = a[1:3]
b[0] = 99
print("slice dan keyin a:", a, "| xotira umumiy:", np.shares_memory(a, b))

a = np.array([10, 20, 30, 40, 50])
c = a[[1, 2]]
c[0] = 99
print("ro'yxat bilan keyin a:", a, "| xotira umumiy:", np.shares_memory(a, c))

d = a[1:3].copy()
print("copy() bilan xotira umumiy:", np.shares_memory(a, d))
Chiqish
slice dan keyin a: [10 99 30 40 50] | xotira umumiy: True
ro'yxat bilan keyin a: [10 20 30 40 50] | xotira umumiy: False
copy() bilan xotira umumiy: False

Nega NumPy shunday qilgan? Tezlik uchun: million qatorli jadvaldan yarmini olish ma'lumotni ko'chirmasdan bir lahzada bo'ladi. Narxi — kutilmagan o'zgarish. Qoida: kesib olgan bo'lakni o'zgartirmoqchi bo'lsangiz, .copy() yozing. np.shares_memory — shubha bo'lsa tekshirish usuli.

Fancy indexing: ro'yxat bilan tanlash

Ketma-ket bo'lmagan qatorlar kerak bo'lsa, indekslar ro'yxatini berasiz. Natija har doim copy.

python3 qator
print(filiallar[[0, 2]])
print(savdo[[0, 2], 5])
print(savdo[:, [0, 6]])
Chiqish
['Chilonzor' 'Sergeli']
[78 36]
[[78 82]
 [64 58]
 [45 57]
 [53 65]]

Boolean mask: shart bilan tanlash

Eng kuchli usul — "qaysi o'rinda" emas, "qanday shartda" tanlash.

python4 qator
past = savdo < 45
print(past.astype(int))
print("45 dan past kunlar soni:", past.sum())
print("o'sha qiymatlar:", savdo[past])
Chiqish
[[0 1 1 1 1 0 0]
 [0 1 1 0 0 0 0]
 [0 1 0 0 1 1 0]
 [0 0 0 0 0 0 0]]
45 dan past kunlar soni: 9
o'sha qiymatlar: [35 40 44 40 32 35 39 31 36]

savdo < 45 — xuddi shu shakldagi True/False jadval (mask). savdo[past] — faqat True joylardagi sonlar, 1 o'lchamli ro'yxat bo'lib chiqadi: jadval shakli saqlanmaydi, chunki har qatorda har xil sonda True bor.

Bir nechta shart — & (va), | (yoki), ~ (emas), har shart qavsda:

python7 qator
dam = np.isin(kunlar, ["Sh", "Ya"])
print("dam olish kunlari maskasi:", dam)
yaxshi_dam = (savdo > 70) & dam
print("dam olish kunida 70 dan yuqori:", savdo[yaxshi_dam])
qator, ustun = np.nonzero(yaxshi_dam)
for q, u in zip(qator, ustun):
    print(f"  {filiallar[q]}, {kunlar[u]}: {savdo[q, u]}")
Chiqish
dam olish kunlari maskasi: [False False False False False  True  True]
dam olish kunida 70 dan yuqori: [78 82]
  Chilonzor, Sh: 78
  Chilonzor, Ya: 82

Python ning and va or so'zlari bu yerda ishlamaydi: ular butun massivni bitta True/False ga aylantirishga urinadi va xato beradi. Massivlar uchun — & va |.

np.nonzero maskadan qaysi o'rinlar True ekanini qaytaradi — shunda "qaysi filial, qaysi kun" degan savolga javob beramiz.

Mask bilan o'zgartirish

Mask faqat o'qish uchun emas. Kassa xatosi bilan manfiy yozilgan summalarni nolga aylantirish:

python4 qator
yozuv = np.array([120, -5, 87, -40, 230])
yozuv[yozuv < 0] = 0
print(yozuv)
print(np.where(savdo[0] >= 60, "yaxshi", "past"))
Chiqish
[120   0  87   0 230]
['yaxshi' 'past' 'past' 'past' 'past' 'yaxshi' 'yaxshi']

yozuv[yozuv < 0] = 0 — "shart bajarilgan joylarga 0 yoz". np.where(shart, A, B) esa asl massivni o'zgartirmaydi: shart rost joyga A, yolg'on joyga B qo'yib, yangi massiv qaytaradi.

Rasmda: haftaning issiqlik xaritasi

Indekslash nimani tanlayotganini ko'rish uchun butun jadvalni rang bilan chizamiz va mask tanlagan kataklarni belgilaymiz:

python9 qator
fig, ax = plt.subplots(figsize=(8, 3.6))
rasm = ax.imshow(savdo, cmap="YlGn")
ax.set_xticks(range(7), kunlar)
ax.set_yticks(range(4), filiallar)
for q, u in zip(*np.nonzero(past)):
    ax.text(u, q, savdo[q, u], ha="center", va="center", color="#c5221f", weight="bold")
fig.colorbar(rasm, label="mln so'm")
ax.set_title("Qizil raqam — 45 dan past kunlar (mask)")
plt.show()

Jadvalni rasm sifatida ko'rish — katta array da qayerda nima borligini tez tushunishning eng oson yo'li. 3-qismda bu usulni Matplotlib bilan chuqurroq o'rganamiz.

Xulosa

  • a[q, u] — bitta element; a[q] — qator; a[:, u] — ustun; manfiy indeks oxiridan sanaydi.
  • Slice start:stop:step, stop kirmaydi; har o'q uchun vergul bilan.
  • Slice — view (asl bilan bir xotira); ro'yxat bilan indekslash va .copy() — copy. Shubha bo'lsa — np.shares_memory.
  • Boolean mask: shart bilan tanlash; shartlar &, |, ~ va qavslar bilan.
  • a[mask] = qiymat aslni o'zgartiradi; np.where yangi massiv qaytaradi.

Mashqlar

  1. savdo dan Sergeli filialining payshanbadan yakshanbagacha savdosini oling.
  2. x = np.arange(10), y = x[::2], y[:] = 0. x qanday bo'ladi? Avval taxmin qiling.
  3. Har filialning eng yaxshi kunini toping (maslahat: argmax, 5-bobda batafsil).
  4. 50 dan past yoki 80 dan yuqori bo'lgan kunlar nechta?

Javoblar

  1. savdo[2, 3:] — Pa, Ju, Sh, Ya.
  2. [0 1 0 3 0 5 0 7 0 9]: y — view, unga yozish x ning juft o'rinlarini o'zgartiradi.
  3. kunlar[savdo.argmax(axis=1)] — har qator bo'yicha eng katta qiymat o'rni.
  4. ((savdo < 50) | (savdo > 80)).sum().

Bu bobni bepul o'qidingiz.

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

Telegramda yozish Narxlar