Məzmuna keç
Educora
Universitet25 dəq29 / 42

NumPy-ın əsasları: massivlər

NumPy massivi (ndarray) ilə tanış ol: tip və forma, massivlərin yaradılması, təkrarlana bilən təsadüfi ədədlər, indeksləmə, kəsiklər, məntiqi maskalar və oxlar üzrə aqreqasiya.

Özünü yoxla
Bu dərsdə öyrənəcəksən
  • ndarray-in atributlarını (ndim, shape, size, dtype) izah etmək və massivin yaddaş həcmini hesablamaq
  • arange, linspace, zeros və toxumlu default_rng ilə massivlər yaratmaq
  • İndeks, kəsik və məntiqi maskalarla verilənləri seçmək, görünüşü surətdən fərqləndirmək
  • axis parametri ilə sətir və sütunlar üzrə statistik göstəriciləri hesablamaq

Hava stansiyası il boyu hər saat temperaturu ölçür — bu, 8760 ədəd deməkdir. Onların orta qiymətini, ən isti günləri və aylıq ortaları adi Python siyahıları və dövrlərlə də hesablamaq olar, amma yavaş və uzun kodla. NumPy (Numerical Python) eyni işi bir sətirlə və dəfələrlə sürətli görür. pandas, matplotlib, SciPy, scikit-learn — Python-da verilənlər elminin bütün alətləri NumPy massivləri üzərində qurulub, ona görə bu modul məhz ondan başlayır.

Tərif
ndarray (N ölçülü massiv)

NumPy-ın əsas obyekti: eyni tipli elementlərdən ibarət, ölçüsü sabit olan çoxölçülü cədvəl. Elementlər yaddaşda bir-birinin ardınca yerləşir, əməliyyatlar isə kompilyasiya olunmuş C kodunda bütün massiv üzərində birdən icra olunur.

ndarray: forma, ölçü və tip

Python siyahısı hər elementi ayrıca obyekt kimi saxlayır və özündə yalnız onlara göstəriciləri (ünvanları) tutur, massiv isə «xam» ədədləri bir blokda saxlayır. Buna görə massiv həm az yer tutur, həm də sürətli emal olunur. Hər massivin dörd əsas atributu var: ndim — ölçülərin (oxların) sayı, shape — hər ox üzrə uzunluqlardan ibarət kortej, size — elementlərin ümumi sayı, dtype — elementlərin tipi.

Python
import numpy as np

temps = np.array([12.5, 14.0, 9.8, 11.2])
print(temps)
print(temps.ndim, temps.shape, temps.size, temps.dtype)
print(temps.itemsize, temps.nbytes)

m = np.array([[1, 2, 3], [4, 5, 6]])
print(m)
print(m.ndim, m.shape, m.size)
print(m * 10)
▸ Gözlənilən nəticə
[12.5 14.   9.8 11.2]
1 (4,) 4 float64
8 32
[[1 2 3]
 [4 5 6]]
2 (2, 3) 6
[[10 20 30]
 [40 50 60]]
m * 10 dövrsüz işləyir: əməl hər elementə tətbiq olunur. Siyahıda isə [1, 2] * 10 siyahını 10 dəfə təkrarlayardı.
size = d₁ · d₂ · … · dₙ nbytes = size · itemsize
burada:
  • noxların sayı (ndim)
  • dₖk-cı ox üzrə uzunluq (shape-in elementi)
  • itemsizebir elementin bayt ilə ölçüsü: float64 və int64 üçün 8, float32 və int32 üçün 4, bool və int8 üçün 1

Forması (2, 3) olan m üçün size = 2 · 3 = 6. temps üçün nbytes = 4 · 8 = 32 bayt.

dtypeBaytDiapazon / dəqiqlikHarada işlənir
bool1True / Falsemaskalar, bayraqlar
uint810 … 255şəkil pikselləri
int324təxminən ±2,1 · 10⁹sayğaclar, indekslər
int648təxminən ±9,2 · 10¹⁸böyük tam ədədlər
float324~7 əhəmiyyətli rəqəmneyron şəbəkələr, GPU
float648~15–16 əhəmiyyətli rəqəmkəsr ədədlər üçün susmaya görə tip

Massivin bütün elementləri eyni tipdə olmalıdır. Müxtəlif tiplər qarışanda NumPy hamısını «ən geniş» tipə çevirir: tam ədəd və kəsr birlikdə float64 verir, ədəd və sətir birlikdə — sətir. astype tipi açıq şəkildə dəyişir; kəsrdən tama çevirəndə kəsr hissə yuvarlaqlaşdırılmır, sadəcə atılır.

Python
import numpy as np

print(np.array([1, 2, 3.5]))
print(np.array([1, 2, '3']))
print(np.array([1.9, -1.9]).astype(np.int32))

small = np.array([100, 120], dtype=np.int8)
print(small + small)
▸ Gözlənilən nəticə
[1.  2.  3.5]
['1' '2' '3']
[ 1 -1]
[-56 -16]

Massivlərin yaradılması

FunksiyaNə yaradır
np.array(data)siyahıdan və ya iç-içə siyahılardan massiv
np.zeros(shape), np.ones(shape), np.full(shape, v)0, 1 və ya v ilə doldurulmuş massiv
np.arange(start, stop, step)range kimi addımlı ardıcıllıq; stop daxil deyil
np.linspace(start, stop, num)bərabər aralıqlı num nöqtə; hər iki uc daxildir
np.eye(n)n × n vahid matris
np.random.default_rng(seed)təsadüfi ədədlər generatoru
Python
import numpy as np

print(np.zeros((2, 3)))
print(np.arange(0, 10, 2))
print(np.linspace(0, 1, 5))
print(np.full(3, 7.5))
print(np.eye(3))
▸ Gözlənilən nəticə
[[0. 0. 0.]
 [0. 0. 0.]]
[0 2 4 6 8]
[0.   0.25 0.5  0.75 1.  ]
[7.5 7.5 7.5]
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
h = (stop − start) / (num − 1) n = ⌈(stop − start) / step⌉h = (stop − start) / (num − 1) n = ⌈(stop − start) / step⌉
burada:
  • hlinspace nöqtələri arasındakı addım
  • narange massivindəki elementlərin sayı
  • ⌈ ⌉yuxarı yuvarlaqlaşdırma

np.linspace(0, 1, 5): h = 1 / 4 = 0,25. np.arange(0, 10, 2): n = ⌈10 / 2⌉ = 5 element.

Kəsr addımlı arange ilə ehtiyatlı ol: 0,1 ikilik sistemdə dəqiq göstərilə bilmir və yuvarlaqlaşdırma xətası son elementin massivə düşüb-düşməməsini dəyişə bilər. Aşağıda stop = 1.3 olsa da, 1,3 massivə daxil olub:

Python
import numpy as np

print(np.arange(0, 1, 0.1).size)
print(np.arange(1, 1.3, 0.1))
print(np.linspace(1, 1.3, 4))
▸ Gözlənilən nəticə
10
[1.  1.1 1.2 1.3]
[1.  1.1 1.2 1.3]

Təsadüfi ədədlər üçün müasir yol generator yaratmaqdır: rng = np.random.default_rng(42). Burada 42 toxumdur (seed): eyni toxumla generator hər dəfə eyni ardıcıllığı verir. Bu, elmi işdə vacibdir — həmkarın sənin kodunu işə salıb eyni nəticəni ala bilməlidir. integers(a, b) yuxarı sərhədi daxil etmir, normal(loc, scale) normal paylanmadan, random() isə [0; 1) aralığından ədədlər qaytarır. Köhnə kodlarda görəcəyin np.random.seed və np.random.rand əvəzinə yeni kodda generatordan istifadə et.

Python
import numpy as np

rng = np.random.default_rng(42)
print(rng.integers(1, 7, size=10))
print(rng.normal(loc=170, scale=8, size=4).round(1))
print(rng.random((2, 3)).round(3))
▸ Gözlənilən nəticə
[1 5 4 3 3 6 1 5 2 1]
[159.6 171.  167.5 169.9]
[[0.45  0.371 0.927]
 [0.644 0.823 0.443]]
On zər atışı, boyu orta hesabla 170 sm olan dörd nəfərin təsadüfi boyu və 2 × 3 ölçülü təsadüfi matris. Kodu yenidən işə salsan, nəticə eyni qalacaq.

İndeksləmə, kəsiklər və məntiqi maskalar

Birölçülü massiv siyahı kimi indekslənir: a[0], a[-1], a[2:5], a[::2]. İkiölçülü massivdə indekslər vergüllə ayrılır: m[sətir, sütun]. İki nöqtə : «bu ox üzrə hamısı» deməkdir: m[:, 1] — ikinci sütun, m[1] — ikinci sətir. Kəsiklər hər ox üzrə ayrıca işləyir, mənfi addım isə sıranı tərsinə çevirir.

Python
import numpy as np

m = np.arange(1, 13).reshape(3, 4)
print(m)
print(m[1, 2], m[-1, -1])
print(m[:, 1])
print(m[0:2, 1:3])
print(m[::2, ::-1])
▸ Gözlənilən nəticə
[[ 1  2  3  4]
 [ 5  6  7  8]
 [ 9 10 11 12]]
7 12
[ 2  6 10]
[[2 3]
 [6 7]]
[[ 4  3  2  1]
 [12 11 10  9]]
reshape(3, 4) 12 elementi 3 sətir və 4 sütuna düzür (növbəti dərsdə ətraflı). m[::2, ::-1] — hər ikinci sətir, sütunlar tərs sırada.
Python
import numpy as np

m = np.arange(1, 13).reshape(3, 4)
row = m[0]
row[0] = 100
print(m[0])

safe = m[1].copy()
safe[0] = -1
print(m[1], safe)
▸ Gözlənilən nəticə
[100   2   3   4]
[5 6 7 8] [-1  6  7  8]

Müqayisə operatoru massivə tətbiq olunanda hər element üçün True və ya False qaytarır — bu, məntiqi maskadır. Maskanı indeks kimi versən, yalnız True olan elementlər seçilir. True 1, False isə 0 kimi hesablandığından mask.sum() şərtə uyğun elementlərin sayını, mask.mean() isə onların payını verir. np.where(şərt, a, b) hər element üçün «əgər…, onda a, yoxsa b» seçimini bir əməldə edir. Aşağıda bir həftənin günorta temperaturları var:

Python
import numpy as np

temps = np.array([21.4, 25.8, 31.2, 28.9, 33.5, 26.1, 19.7])
hot = temps > 28
print(hot)
print(temps[hot])
print(np.flatnonzero(hot))
print(hot.sum(), 'hot days,', f'{hot.mean():.0%} of the week')
print(temps[(temps > 20) & (temps < 27)])
print(np.where(temps > 30, 30.0, temps))
▸ Gözlənilən nəticə
[False False  True  True  True False False]
[31.2 28.9 33.5]
[2 3 4]
3 hot days, 43% of the week
[21.4 25.8 26.1]
[21.4 25.8 30.  28.9 30.  26.1 19.7]
np.flatnonzero True olan elementlərin indekslərini qaytarır: 0-dan saydıqda 2, 3 və 4 nömrəli günlər. Sonuncu sətir 30-dan yuxarı qiymətləri 30 ilə əvəz edir.
Nümunə 1: indekslər və oxlar əl ilə

a = np.arange(12).reshape(3, 4) üçün kodu işə salmadan tap: a) a[1:, ::2]; b) a.sum(axis=0) və a.sum(axis=1) və onların formaları; c) (a % 5 == 0).sum().

Həllini göstər
a = [[0 1 2 3], [4 5 6 7], [8 9 10 11]].
a) 1: — 1 və 2 nömrəli sətirlər, ::2 — 0 və 2 nömrəli sütunlar: [[4 6], [8 10]].
b) axis=0 sətirləri «sıxır», hər sütunun cəmi qalır: [0+4+8, 1+5+9, 2+6+10, 3+7+11] = [12 15 18 21], forma (4,).
axis=1 hər sətrin cəmini verir: [6 22 38], forma (3,).
c) 5-ə bölünən elementlər 0, 5 və 10-dur, maskada 3 dənə True var: cavab 3.

Aqreqasiya və axis parametri

sum, mean, min, max, std, argmax, cumsum kimi funksiyalar çoxlu ədədi bir ədədə və ya daha kiçik massivə «yığır» — buna aqreqasiya deyilir. axis verilməsə, hesablama bütün massiv üzrə aparılır. axis=0 birinci ox (sətirlər) boyunca hesablayır və hər sütun üçün bir nəticə verir; axis=1 sütunlar boyunca hesablayır və hər sətir üçün bir nəticə verir. Aşağıda 4 tələbənin (sətirlər) riyaziyyat, fizika və kimyadan (sütunlar) balları var:

Python
import numpy as np

scores = np.array([[85, 92, 78],
                   [67, 74, 81],
                   [93, 88, 95],
                   [72, 65, 70]])
print(scores.shape, scores.sum())
print(scores.mean(axis=0))
print(scores.mean(axis=1).round(2))
print(scores.max(axis=0), scores.argmax(axis=0))
print(scores.std(axis=0).round(2))
print(scores.std(axis=0, ddof=1).round(2))
print(scores.cumsum(axis=1)[0])
▸ Gözlənilən nəticə
(4, 3) 960
[79.25 79.75 81.  ]
[85. 74. 92. 69.]
[93 92 95] [2 0 2]
[10.3  10.83  9.03]
[11.9  12.5  10.42]
[ 85 177 255]
Fənlər üzrə orta ballar 79,25; 79,75 və 81-dir; tələbələrin ortaları 85, 74, 92 və 69. argmax(axis=0) hər fəndə ən yaxşı tələbənin indeksini verir: riyaziyyat və kimyada 2 nömrəli, fizikada 0 nömrəli.
x̄ = (1/n) · ∑ xᵢ σ = √( ∑ (xᵢ − x̄)² / (n − ddof) )x̄ = (1/n) · ∑ xᵢ σ = √( ∑ (xᵢ − x̄)² / (n − ddof) )
burada:
  • x̄ədədi orta (mean)
  • nqiymətlərin sayı
  • σstandart meyl (std), qiymətlərin ortadan orta hesabla nə qədər uzaqlaşdığı
  • ddof0 — baş məcmu üçün (NumPy-da susmaya görə), 1 — seçmə üçün (sürüşməsiz dispersiya)

np.std susmaya görə n-ə bölür, statistika dərslikləri və pandas-dakı Series.std isə n − 1-ə. Eyni nəticə üçün ddof=1 ötür.

Nümunə 2: standart meyl əl ilə

x = [2, 4, 4, 4, 5, 5, 7, 9]. np.std(x) və np.std(x, ddof=1) nəyə bərabər olacaq?

Həllini göstər
x̄ = 40 / 8 = 5.
Ortadan kənarlaşmaların kvadratları: 9, 1, 1, 1, 0, 0, 4, 16; cəmi 32.
ddof = 0: σ² = 32 / 8 = 4, σ = 2.
ddof = 1: s² = 32 / 7 ≈ 4,571, s ≈ 2,138.
n böyüdükcə iki cavab arasındakı fərq kiçilir.

Bu biliklər harada lazım olacaq? pandas cədvəllərinin sütunları NumPy massivləridir; scikit-learn verilənləri (n × d) formalı massiv kimi qəbul edir; şəkillərin emalı, siqnallar, maliyyə sıraları və fizika modelləri — hamısı massivlər üzərində əməliyyatlardır. Növbəti dərsdə dövrləri tamamilə vektorlaşdırılmış kodla əvəz etməyi və xətti cəbri öyrənəcəksən.

Tapşırıq

sales massivində kiçik kafenin 4 həftəlik satışları var (sətirlər — həftələr, sütunlar — bazar ertəsindən bazara qədər günlər). Ayrı-ayrı sətirlərdə çap et: 1) hər həftənin ümumi satışı; 2) 4 həftə üzrə ən çox satış olan həftə gününün indeksi (0 = bazar ertəsi); 3) satışın 100-dən çox olduğu günlərin sayı. Dövr işlətmə.

Tapşırıq · Python
import numpy as np

sales = np.array([[80, 95, 110, 90, 130, 150, 70],
                  [85, 100, 105, 95, 140, 160, 75],
                  [90, 92, 120, 88, 125, 155, 80],
                  [78, 99, 115, 97, 135, 165, 72]])
# 1) total per week
# 2) index of the best weekday
# 3) number of days above 100
▸ Gözlənilən nəticə
[725 760 750 761]
5
12
Tapşırıq

Sensorun ölçmələrində mənfi qiymətlər xətadır. 1) np.where ilə mənfi qiymətləri 0.0 ilə əvəz edib yeni massivi çap et; 2) ilkin massivdə 10-dan böyük ölçmələrin ortasını 1 onluq rəqəmə qədər yuvarlaqlaşdırıb çap et.

Tapşırıq · Python
import numpy as np

readings = np.array([12.5, -3.0, 8.4, 15.1, -1.2, 20.3, 9.9, 11.0])
# 1) negatives -> 0.0
# 2) mean of readings > 10, rounded to 1 decimal
▸ Gözlənilən nəticə
[12.5  0.   8.4 15.1  0.  20.3  9.9 11. ]
14.7

Əsas fikirlər

  • ndarray eyni tipli elementləri yaddaşda ardıcıl saxlayır; əsas atributları ndim, shape, size, dtype-dır, nbytes = size · itemsize.
  • arange stop-u daxil etmir; kəsr addım üçün hər iki ucu daxil edən linspace daha etibarlıdır.
  • Təkrarlana bilən təsadüfi ədədlər üçün np.random.default_rng(seed) generatorundan istifadə et.
  • Kəsik görünüşdür: onu dəyişmək əsl massivi dəyişir; müstəqil surət üçün .copy().
  • Maskaları &, |, ~ və mötərizələrlə birləşdir; mask.sum() say, mask.mean() pay verir.
  • axis=k k oxunu nəticənin formasından çıxarır; np.std susmaya görə ddof=0 işlədir.

Özünü yoxla

10 sual. Hər düzgün cavab XP qazandırır.

1 / 10
np.zeros((3, 4)).sum(axis=0) nəticəsinin forması nədir?