Гузариш ба мундариҷа
Мавзӯи 3 аз 6

Индексҳо ва бурришҳо

Ин барои чӣ лозим аст

Маълумотро хеле кам пурра истифода мебаранд. Танҳо даромади ҳафтаи охир, танҳо як сутуни ҷадвал — «нархҳо», танҳо пораи майдон бо ҳосил, танҳо унсурҳо бо тартиби муайян лозиманд. Барои ин индексгузорӣ вуҷуд дорад — роҳҳои нишон додан, ки кадом унсурҳои массивро гирифтан лозим.

Дар numpy индексгузорӣ ба бурришҳои рӯйхатҳои Python монанд аст, вале бештар карда метавонад: дар як навишт сатрҳо ва сутунҳои ҷадвалро интихоб кардан, росткунҷа буридан, унсурҳоро аз рӯи рӯйхати рақамҳо ҷамъ кардан мумкин. Дар ин мавзӯъ ҳамаи ин роҳҳоро ва як хусусияти муҳими numpy-ро баррасӣ мекунем: бурриш маълумотро нусха намекунад.

Индекс ва бурриш дар массиви якченака

Индекс — рақами унсур, аз сифр ҳисоб мешавад. Индекси манфӣ аз охир ҳисоб мекунад: -1 — унсури охирин.

Бурриш a[start:stop:step] — пораи массив аз start то stop (бе stop) бо қадами step. Ҳар қисмро партофтан мумкин: он гоҳ ибтидо, охир ё қадами 1 гирифта мешавад.

import numpy as np

a = np.array([5, 8, 2, 9, 4, 7])
print(a[0], a[-1])
print(a[1:4])
print(a[:3])
print(a[3:])
print(a[::2])
print(a[::-1])

Натиҷа:

5 7
[8 2 9]
[5 8 2]
[9 4 7]
[5 2 4]
[7 4 9 2 8 5]

Ҳамааш мисли рӯйхатҳо: a[::-1] — массив баръакс, a[::2] — ҳар унсури дуюм.

Рақамгузорӣ аз як

Дар масъалаҳо унсурҳоро аксар вақт аз 1 рақам мезананд ва ҳадҳоро дохил мекунанд: «аз l-ум то r-ум». Дар Python ин бурриши a[l - 1 : r] аст: ҳадди чап як воҳид ҷой иваз мекунад, рост бошад не, зеро stop ба бурриш дохил намешавад.

import numpy as np

a = np.array([10, 20, 30, 40, 50])
l, r = 2, 4
print(a[l - 1:r])

Натиҷа:

[20 30 40]

Ҷадвал: индексҳо бо вергул

Дар массиви дученака ду индекс нишон додан лозим: рақами сатр ва рақами сутун. Дар numpy онҳоро бо вергул дар як қавс менависанд:

import numpy as np

m = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8],
              [9, 10, 11, 12]])
print(m[2, 1])
print(m[0, -1])
print(m[0])
print(m[:, 3])

Натиҷа:

10
4
[1 2 3 4]
[ 4  8 12]
  • m[2, 1] — сатри 2, сутуни 1;
  • m[0] — тамоми сатри 0 (индекси дуюмро навиштан шарт нест);
  • m[:, 3] — тамоми сутуни 3. Дунуқта : маънои «ҳама аз рӯи ин меҳвар»-ро дорад: ҳамаи сатрҳо ва аз онҳо — сутуни 3.

Навишти m[2][1] ҳам кор мекунад (аввал сатр, баъд аз он унсур гирифта мешавад), вале m[2, 1] — услуби дурусти numpy аст: кӯтоҳтар ва тезтар.

Бурриши ҷадвал — росткунҷа

Агар аз рӯи ҳарду меҳвар бурриш нависед, пораи росткунҷаи ҷадвал ҳосил мешавад:

import numpy as np

m = np.array([[1, 2, 3, 4],
              [5, 6, 7, 8],
              [9, 10, 11, 12]])
print(m[0:2, 1:3])
print(m[1:, ::2])
print(m[:, :2])

Натиҷа:

[[2 3]
 [6 7]]
[[ 5  7]
 [ 9 11]]
[[ 1  2]
 [ 5  6]
 [ 9 10]]

m[0:2, 1:3] чунин хонда мешавад: сатрҳои 0 ва 1, сутунҳои 1 ва 2. Ҳадҳои рост, мисли ҳамеша, дохил намешаванд.

Бо росткунҷа дарҳол мисли массив кор кардан мумкин — масалан, ҳосили ҷамъ ё миёнаи онро ҳисоб кардан:

import numpy as np

m = np.arange(1, 13).reshape(3, 4)
print(m)
part = m[1:3, 0:2]
print(part)
print(part.sum(), part.mean())

Натиҷа:

[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
[[ 5  6]
 [ 9 10]]
30 7.5

Маслиҳат: агар шубҳа доред, ки бурриш дуруст навишта шудааст, аввал худи пораро чоп кунед, баъд аз рӯи он ҳисоб кунед.

Бурриш — тиреза аст, на нусха

Фарқи муҳим аз рӯйхатҳо. Бурриши рӯйхати Python рӯйхати нав месозад. Бурриши массиви numpy бошад маълумотро нусха намекунад: вай ба ҳамон қисми хотира менигарад, ки массиви аслӣ. Чунин бурришро намоиш (view) меноманд — ин мисли тирезаест, ки аз он қисми массив намоён аст.

import numpy as np

a = np.arange(5)
part = a[1:4]
part[:] = 0
print(part)
print(a)

Натиҷа:

[0 0 0]
[0 0 0 0 4]

Мо part-ро тағйир додем, вале a ҳам тағйир ёфт. Ин дар маълумоти калон хотира ва вақтро сарфа мекунад, вале метавонад ҳайрон кунад. Агар нусхаи мустақил лозим бошад — .copy()-ро даъват кунед:

import numpy as np

a = np.arange(5)
part = a[1:4].copy()
part[:] = 0
print(a)

Натиҷа:

[0 1 2 3 4]

Навиштан аз рӯи индексҳо ва бурришҳо

Тавассути индексҳо ва бурришҳо на танҳо хондан, балки навиштан ҳам мумкин:

import numpy as np

m = np.zeros((3, 4), dtype=int)
m[0, 0] = 5
m[1] = [1, 2, 3, 4]
m[:, 3] = 9
m[2, 1:3] = 7
print(m)

Натиҷа:

[[5 0 0 9]
 [1 2 3 9]
 [0 7 7 9]]

Қимати тарафи рост ба тамоми пораи интихобшуда паҳн мешавад (ин ҳамон broadcasting аст): m[:, 3] = 9 нӯҳро ба ҳар сатри сутуни 3 менависад.

Интихоб аз рӯи рӯйхати индексҳо

Агар ба қавсҳои мураббаъ рӯйхат ё массиви индексҳо-ро диҳед, numpy унсурҳоро аз ҳамин мавқеъҳо бо тартиби нишондодашуда ҷамъ мекунад. Инро fancy indexing («индексгузории аҷиб») меноманд:

import numpy as np

colors = np.array(["red", "green", "blue", "black"])
print(colors[[2, 0, 2]])
idx = np.array([3, 1])
print(colors[idx])

Натиҷа:

['blue' 'red' 'blue']
['black' 'green']

Индексҳо метавонанд бо ҳар тартиб оянд ва такрор шаванд. Бинобар ин ҷой иваз кардани унсурҳо хеле қулай аст: массиви индексҳо нишон медиҳад, ки ба ҳар ҷой кадом унсурро гузоштан лозим.

import numpy as np

word = np.array(list("мор"))
order = np.array([2, 1, 0])
print(word[order])
print("".join(word[order]))

Натиҷа:

['р' 'о' 'м']
ром

Баръакси бурриш, натиҷаи fancy indexing — массиви нав (нусха) аст, на тиреза.

Сатрҳо ва катакҳои ҷадвал аз рӯи рӯйхат

Дар ҷадвал рӯйхати индексҳо сатрҳо-ро интихоб мекунад:

import numpy as np

m = np.arange(12).reshape(3, 4)
print(m[[2, 0]])
print(m[:, [0, 3]])
print(m[[0, 2], [1, 3]])

Натиҷа:

[[ 8  9 10 11]
 [ 0  1  2  3]]
[[ 0  3]
 [ 4  7]
 [ 8 11]]
[ 1 11]
  • m[[2, 0]] — сатрҳои 2 ва 0;
  • m[:, [0, 3]] — ҳамаи сатрҳо, сутунҳои 0 ва 3;
  • m[[0, 2], [1, 3]] — ҷуфтҳои индексҳо: катакҳои (0, 1) ва (2, 3). Ин росткунҷа нест, балки унсурҳои алоҳида аст!

Дар дохил чӣ тавр кор мекунад

Массиви numpy ададҳоро дар як пораи яклухти хотира нигоҳ медорад ва медонад, ки аз болои он чӣ тавр «қадам занад»: то унсури навбатӣ дар сатр чанд байт ва то сатри навбатӣ чанд байт. Бурриши монанди a[::2] ададҳоро интиқол намедиҳад, балки «нигоҳи» навро ба ҳамон хотира бо қадами дигар месозад — бинобар ин он хеле тез аст ва бинобар ин тағйирот дар бурриш дар массиви аслӣ намоён мешаванд.

Рӯйхати индексҳоро бо як қадам тасвир кардан мумкин нест ([2, 0, 2] ба пешу пас ҷаҳида меравад), бинобар ин fancy indexing унсурҳоро ба массиви нав ҷамъ мекунад — ин ҳамеша нусха аст.

Монандӣ: бурриш — чорчӯбаест, ки ба расм гузошта шудааст: аз он қисми расм намоён аст ва агар дар дохили чорчӯба чизе кашед, худи расм тағйир меёбад. Fancy indexing — суратҳои пораҳои интихобшуда, ки бо тартиби лозимӣ ба албом часпонида шудаанд.

Хатоҳои маъмул

1. Фаромӯш кардан, ки ҳадди рост дохил намешавад. «Унсурҳо аз 2-юм то 4-ум» ҳангоми рақамгузорӣ аз як — ин a[1:4] аст, на a[1:3] ва на a[2:4].

2. Берун рафтан аз ҳудуди массив. Индекси алоҳида бояд вуҷуд дошта бошад:

# хато: дар массив ҳамагӣ 3 унсур аст
import numpy as np
a = np.array([1, 2, 3])
print(a[3])

Натиҷа:

IndexError: index 3 is out of bounds for axis 0 with size 3

Бурриш берун аз ҳудуд бошад хато намедиҳад — танҳо он чиро, ки ҳаст, бармегардонад: a[1:100] натиҷаи [2 3] медиҳад.

3. Ногаҳон тавассути бурриш маълумоти аслиро тағйир додан. Агар бурриш тағйир дода шавад, вале массиви аслӣ ҳанӯз лозим бошад — .copy() кунед.

4. m[[0, 2], [1, 3]] ва росткунҷаро омехтан. Ду рӯйхат — ҷуфтҳои катакҳо. Барои гирифтани сатрҳои 0 ва 2 ва аз онҳо сутунҳои 1 ва 3, дар ду қадам интихоб кунед:

import numpy as np

m = np.arange(12).reshape(3, 4)
print(m[[0, 2]][:, [1, 3]])

Натиҷа:

[[ 1  3]
 [ 9 11]]

5. Индексҳо барои ҷойивазкунӣ — аз як. Агар ҷойивазкунӣ дар маълумоти воридотӣ бо рақамҳо аз 1 навишта шуда бошад, пеш аз истифода аз тамоми массив якро тарҳ кунед: p = np.array(...) - 1. Вагарна ҷойивазшавӣ ё IndexError ҳосил мешавад.

Ёддошти кӯтоҳ

Чӣ лозим Чӣ тавр навиштан
унсур a[i], m[i, j]
аз охир a[-1] — охирин
пора a[start:stop] — stop дохил намешавад
ҳар дуюм / баръакс a[::2], a[::-1]
аз l-ум то r-ум (рақамгузорӣ аз 1) a[l - 1:r]
сатр / сутуни ҷадвал m[i], m[:, j]
росткунҷа m[r1:r2, c1:c2]
нусхаи мустақил a[1:4].copy()
ба пора навиштан m[:, 0] = 0, m[1] = [...]
унсурҳо аз рӯи рӯйхати индексҳо a[[3, 0, 0]] — нусха, бо тартиби додашуда
сатрҳо аз рӯи рӯйхат m[[2, 0]]
катакҳои алоҳида m[[r1, r2], [c1, c2]]