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

Массивҳои numpy

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

Тасаввур кунед, ки шумо рӯйхати як миллион нарх доред ва онҳоро аз доллар ба сомонӣ гузарондан лозим аст. Дар Python-и одӣ давра (цикл) навишта мешавад: нархро гир, зарб зан, ба рӯйхати нав гузор — ва ҳамин тавр як миллион маротиба. Ин кор мекунад, вале суст ва дароз.

numpy чунин масъалаҳоро бо як сатр ҳал мекунад: prices * 90. Ин китобхонаи асосии Python барои ҳисоббарорӣ аст. pandas, scikit-learn, SciPy, matplotlib дар асоси он сохта шудаанд — қариб тамоми таҳлили маълумот ва омӯзиши мошинӣ. Асоси он массив (ndarray) аст: маҷмӯи ададҳои як навъ, ки бо он якбора, бе давраҳо кор кардан мумкин аст. Дар ин мавзӯъ мебинем, ки массивҳоро чӣ тавр месозанд, шакл ва навъи онҳоро чӣ тавр мефаҳманд ва чӣ тавр чоп мекунанд.

Пайваст кардан

import numpy as np
print(np.__version__)

Натиҷа:

1.26.4

Ихтисораи np — қабулшуда аст: онро дар ҳуҷҷатҳо, мақолаҳо ва коди дигарон истифода мебаранд. Ҳамеша import numpy as np нависед, он гоҳ ҳар мисол аз интернет бе тағйир кор мекунад.

Массив аз рӯйхат

Массив — маҷмӯи тартибдодашудаи унсурҳо, монанди рӯйхат (list). Он бо функсияи np.array сохта мешавад, ки ба он рӯйхати одиро медиҳанд:

import numpy as np

a = np.array([3, 1, 4, 1, 5])
print(a)
print(type(a))
print(len(a), a[0], a[-1])

Натиҷа:

[3 1 4 1 5]
<class 'numpy.ndarray'>
5 3 5

Диққат диҳед: массив бе вергул чоп мешавад — ҳамин тавр онро аз рӯйхат осон фарқ кардан мумкин. Индексҳо, len ва индексҳои манфӣ мисли рӯйхатҳо кор мекунанд.

Амалҳо бо тамоми массив якбора

Фарқи асосӣ аз рӯйхат: арифметика ба ҳар як унсур татбиқ мешавад.

import numpy as np

a = np.array([1, 2, 3])
print(a + 10)
print(a * a)
print(a / 2)
print(a ** 2)

Натиҷа:

[11 12 13]
[1 4 9]
[0.5 1.  1.5]
[1 4 9]

Бо рӯйхат муқоиса кунед — дар он ҷо * маънои «такрор кун»-ро дорад:

nums = [1, 2, 3]
print(nums * 2)
print([x * 2 for x in nums])

Натиҷа:

[1, 2, 3, 1, 2, 3]
[2, 4, 6]

Чунин услуб — як амал болои тамоми массив ба ҷои давра — векторизатсия ном дорад. Он кӯтоҳтар ва хеле тезтар аст: дар мавзӯи оянда муфассал баррасӣ мекунем.

Навъи унсурҳо: dtype

Дар рӯйхати Python ададҳо, сатрҳо ва ҳар чизи дигар омехта буда метавонанд. Дар массиви numpy ҳамаи унсурҳо як навъ доранд. Навъ дар хосияти dtype (аз data type — навъи маълумот) нигоҳ дошта мешавад:

import numpy as np

print(np.array([1, 2, 3]).dtype)
print(np.array([1.5, 2, 3]).dtype)
print(np.array([1, 2], dtype=float))
print(np.array(["a", "bb"]).dtype)

Натиҷа:

int32
float64
[1. 2.]
<U2
  • int32 — ададҳои бутун. Дар сайт (Python дар браузер) ададҳои бутун бо пешфарз 32-битӣ мебошанд. Дар компютери шумо бо Linux ё macOS int64 хоҳад буд — ин муқаррарӣ аст.
  • float64 — ададҳои касрӣ. Як адади касрӣ кифоя аст, ки ҳамаи унсурҳо касрӣ шаванд: [1. 2.] — ин 1.0 ва 2.0 аст, numpy танҳо сифрро пас аз нуқта чоп намекунад.
  • <U2 — сатрҳо бо дарозии то 2 аломат. Дар ин курс ба мо қариб ҳамеша ададҳо лозиманд.

Навъро ҳангоми сохтан (dtype=float, dtype=int) додан ё массиви тайёрро бо усули astype иваз кардан мумкин:

import numpy as np

x = np.array([2.7, -1.2, 3.9])
print(x.astype(int))
print(np.array([1, 2, 3]).astype(float))

Натиҷа:

[ 2 -1  3]
[1. 2. 3.]

astype(int) қисми касриро мепартояд (яклухт намекунад!): 2.7 → 2, -1.2 → -1.

Чаро андозаи ададҳои бутун муҳим аст

Адади бутуни одии Python метавонад ҳар қадар калон бошад. Адади бутуни numpy — не: int32 ададҳоро тақрибан то 2 · 109, int64 — то 9 · 1018 ҷой медиҳад. Агар натиҷа ҷой нагирад, numpy дар бораи хато хабар намедиҳад — танҳо адади нодуруст ҳосил мешавад. Бинобар ин, агар ҳосили ҷамъ ё ҳосили зарб калон шуда тавонад, навъро ошкоро диҳед: dtype=np.int64.

Массив аз сатри воридот

Дар масъалаҳо маълумот ҳамчун сатр меояд, масалан "2.5 4 10". Онро дарҳол ба массиви ададҳо табдил додан қулай аст: бо split() ҷудо кунед ва dtype-ро нишон диҳед:

import numpy as np

line = "2.5 4 10"
x = np.array(line.split(), dtype=float)
print(x)
print(x * 2)

Натиҷа:

[ 2.5  4.  10. ]
[ 5.  8. 20.]

line.split() рӯйхати сатрҳои ['2.5', '4', '10']-ро медиҳад, dtype=float бошад ҳар сатрро ба адад табдил медиҳад. Фосилаҳои дохили [ 2.5 4. 10. ]-ро numpy худаш илова мекунад, то сутунчаҳои ададҳо баробар бошанд.

Пайдарпайиҳои тайёр

Аксар вақт массивро ворид намекунанд, балки аз рӯи қоида месозанд.

np.arange(start, stop, step) — монанди range: аз start то stop, ҳадди рост дохил намешавад. Баръакси range, қадам метавонад касрӣ бошад:

import numpy as np

print(np.arange(5))
print(np.arange(1, 10, 2))
print(np.arange(0, 1, 0.25))

Натиҷа:

[0 1 2 3 4]
[1 3 5 7 9]
[0.   0.25 0.5  0.75]

np.linspace(a, b, n) — маҳз n нуқта аз a то b бо масофаи баробар, ҳарду ҳад дохил мешаванд. Вақте қулай аст, ки шумораи нуқтаҳо маълум аст, на қадам:

import numpy as np

print(np.linspace(0, 10, 3))
print(np.linspace(0, 1, 5))
print(np.linspace(1, 2, 2))

Натиҷа:

[ 0.  5. 10.]
[0.   0.25 0.5  0.75 1.  ]
[1. 2.]

Қадам байни нуқтаҳои ҳамсоя ба (b - a) / (n - 1) баробар аст: барои n нуқта n - 1 фосила ҳосил мешавад.

Массивҳо аз қиматҳои якхела: np.zeros — аз сифрҳо, np.ones — аз якҳо, np.full — аз ҳар адад:

import numpy as np

print(np.zeros(4))
print(np.ones(3, dtype=int))
print(np.full(3, 7))

Натиҷа:

[0. 0. 0. 0.]
[1 1 1]
[7 7 7]

zeros ва ones бо пешфарз ададҳои касрӣ месозанд — агар ададҳои бутун лозим бошанд, dtype=int илова кунед.

Массивҳои дученака

Массив метавонад якчанд меҳвар (axis, ченак) дошта бошад. Якченака — қатори ададҳо, дученака — ҷадвал аз сатрҳо ва сутунҳо. Онро аз рӯйхати рӯйхатҳо месозанд:

import numpy as np

m = np.array([[1, 2, 3],
              [4, 5, 6]])
print(m)
print(m.shape)
print(m.ndim)
print(m.size)

Натиҷа:

[[1 2 3]
 [4 5 6]]
(2, 3)
2
6

Се хосияти асосии шакл:

Хосият Маъно Дар ин ҷо
shape андозаҳо аз рӯи ҳар меҳвар (кортеж, tuple) (2, 3) — 2 сатр, 3 сутун
ndim чанд меҳвар 2
size ҳамагӣ чанд унсур 6

Дар массиви якченака shape — кортеж аз як адад аст, масалан (5,). Вергул лозим аст, то Python фаҳмад, ки ин кортеж аст.

Ҷадвали сифрҳоро бо додани андозаҳо ҳамчун кортеж месозанд:

import numpy as np

z = np.zeros((2, 4), dtype=int)
print(z)
print(z.shape)

Натиҷа:

[[0 0 0 0]
 [0 0 0 0]]
(2, 4)

Тағйир додани шакл: reshape

Усули reshape ҳамон унсурҳоро аз рӯи шакли нав ҷойгир мекунад:

import numpy as np

a = np.arange(6)
print(a)
print(a.reshape(2, 3))
print(a.reshape(3, 2))

Натиҷа:

[0 1 2 3 4 5]
[[0 1 2]
 [3 4 5]]
[[0 1]
 [2 3]
 [4 5]]

Унсурҳо ҷадвалро сатр ба сатр пур мекунанд: аввал тамоми сатри якум, баъд дуюм. Шумораи унсурҳо бояд мувофиқ ояд: аз 6 унсур 2×3 ё 3×2 сохтан мумкин, вале 4×2 не. Муфассалтар дар бораи шакл — дар мавзӯи «Шакли массивҳо».

Массивро чӣ тавр чоп кардан

print(a) массивро дар формати numpy — бо қавсҳо чоп мекунад. Дар масъалаҳо одатан қатори оддии ададҳо бо фосила лозим аст. Барои массиви якченака кушодан бо * мувофиқ аст:

import numpy as np

a = np.array([1, 2, 3])
print(a)
print(*a)
print(*(a * 1.5))

Натиҷа:

[1 2 3]
1 2 3
1.5 3.0 4.5

print(*a) унсурҳоро ба print якто-якто медиҳад, гӯё шумо print(a[0], a[1], a[2]) навиштаед. Ададҳои касрӣ пурра чоп мешаванд: 3.0, на 3..

Ҷадвалро сатр ба сатр чоп мекунанд — давраи for аз болои массиви дученака сатрҳои онро мегузарад:

import numpy as np

m = np.arange(1, 7).reshape(2, 3)
for row in m:
    print(*row)

Натиҷа:

1 2 3
4 5 6

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

Рӯйхати Python — қатори истинодҳо ба объектҳои алоҳида аст, ки дар хотира пароканда ҷойгиранд. Ҳар адад дар рӯйхат объекти комил бо навъи худ аст. Бинобар ин ҳангоми ҳар x * 2 Python месанҷад: ин чӣ гуна объект аст, оё онро зарб кардан мумкин аст, — ва объекти нав месозад.

Массиви numpy дигар хел сохта шудааст: ин як пораи яклухти хотира аст, ки дар он ададҳо зич паҳлӯи ҳам хобидаанд, ҳама як андоза (масалан, барои float64 ҳар кадом 8 байт). Навъ пешакӣ маълум аст — он дар dtype навишта шудааст, — бинобар ин санҷидани ҳар унсур лозим нест. Амали a * 2 ба дохили numpy меравад, ки дар он ҷо давра аз болои ин пораи хотира бо забони тези C иҷро мешавад.

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

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

1. Интизор шудан, ки * дар рӯйхат ададҳоро зарб мекунад. Зарби унсур ба унсур танҳо дар массивҳо кор мекунад:

prices = [10, 20]
print(prices * 3)

Натиҷа:

[10, 20, 10, 20, 10, 20]

Ислоҳ: аввал ба массив табдил диҳед — np.array(prices) * 3.

2. Ҳангоми хондани воридот dtype-ро фаромӯш кардан. Бе он массив аз сатрҳо иборат мешавад ва арифметика вайрон мешавад:

# хато: массив аз сатрҳо
import numpy as np
x = np.array("1 2 3".split())
print(x * 2)

Натиҷа:

numpy.core._exceptions._UFuncNoLoopError: ufunc 'multiply' did not contain a loop with signature matching types (dtype('<U1'), dtype('int32')) -> None

Ислоҳ: np.array("1 2 3".split(), dtype=int).

3. arange ва linspace-ро омехтан. np.arange(0, 1, 0.25) 1-ро дохил намекунад, np.linspace(0, 1, 5) бошад дохил мекунад. Агар «маҳз n нуқта бо охирҳо» лозим бошад — ин linspace аст.

4. Андозаҳои ҷадвалро на ҳамчун кортеж додан. np.zeros(2, 3) — хато: аргументи дуюми функсия dtype аст. Дуруст — np.zeros((2, 3)), бо қавсҳои дукарата.

# хато: андозаҳо бе кортеж
import numpy as np
print(np.zeros(2, 3))

Натиҷа:

TypeError: Cannot interpret '3' as a data type

5. reshape бо андозаҳои номувофиқ. Унсурҳо бояд маҳз кифоя бошанд:

# хато: 6 унсурро ба 4×2 ҷойгир кардан мумкин нест
import numpy as np
print(np.arange(6).reshape(4, 2))

Натиҷа:

ValueError: cannot reshape array of size 6 into shape (4,2)

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

Чӣ лозим Чӣ тавр навиштан
пайваст кардани numpy import numpy as np
массив аз рӯйхат np.array([1, 2, 3])
массив аз сатри воридот np.array(input().split(), dtype=float)
навъи унсурҳо a.dtype, иваз кардан — a.astype(int)
ададҳои бутуни калон dtype=np.int64
монанди range np.arange(start, stop, step) — stop дохил намешавад
n нуқта аз a то b np.linspace(a, b, n) — ҳарду ҳад дохиланд
сифрҳо / якҳо / адад np.zeros(n), np.ones(n), np.full(n, x)
ҷадвали сифрҳо np.zeros((сатрҳо, сутунҳо))
шакл, шумораи меҳварҳо, андоза a.shape, a.ndim, a.size
шакли нав a.reshape(сатрҳо, сутунҳо) — сатр ба сатр пур мекунад
чоп бо фосила print(*a)
чопи ҷадвал for row in m: print(*row)