İçeriğe geç
Educora
Üniversite25 dk29 / 42

NumPy'ın temelleri: diziler

NumPy dizisiyle (ndarray) tanış: tür ve şekil, dizi oluşturma, tekrarlanabilir rastgele sayılar, indeksleme, dilimleme, mantıksal maskeler ve eksenler boyunca özetleme.

Kendini test et
Bu derste öğreneceklerin
  • ndarray özniteliklerini (ndim, shape, size, dtype) açıklamak ve bir dizinin bellekte kapladığı yeri hesaplamak
  • arange, linspace, zeros ve tohumlu default_rng ile diziler oluşturmak
  • İndeks, dilim ve mantıksal maskelerle veri seçmek, görünümü kopyadan ayırt etmek
  • axis parametresiyle satırlar ve sütunlar boyunca istatistikler hesaplamak

Bir meteoroloji istasyonu bir yıl boyunca her saat sıcaklığı ölçüyor; bu, 8760 sayı demek. Ortalamayı, en sıcak günleri ve aylık ortalamaları sıradan Python listeleri ve döngülerle de hesaplayabilirsin ama yavaş ve uzun bir kodla. NumPy (Numerical Python) aynı işi tek satırda ve kat kat daha hızlı yapar. pandas, matplotlib, SciPy, scikit-learn: Python'daki bütün veri bilimi araçları NumPy dizileri üzerine kuruludur; bu yüzden modül tam da buradan başlıyor.

Tanım
ndarray (N boyutlu dizi)

NumPy'ın temel nesnesi: aynı türden elemanlardan oluşan, boyutu sabit, çok boyutlu bir ızgara. Elemanlar bellekte art arda durur; işlemler ise derlenmiş C kodunda dizinin tamamı üzerinde bir kerede yürütülür.

ndarray: şekil, boyut ve tür

Bir Python listesi her elemanı ayrı bir nesne olarak tutar ve kendisi yalnızca onlara işaretçiler (adresler) saklar; dizi ise “ham” sayıları tek bir blokta saklar. Bu yüzden dizi hem daha az yer kaplar hem de daha hızlı işlenir. Her dizinin dört temel özniteliği vardır: ndim boyut (eksen) sayısı, shape her eksendeki uzunlukları veren demet, size toplam eleman sayısı, dtype ise elemanların türüdür.

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)
▸ Beklenen çıktı
[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öngüsüz çalışır: işlem her elemana uygulanır. Bir listede ise [1, 2] * 10 listeyi 10 kez tekrarlardı.
size = d₁ · d₂ · … · dₙ nbytes = size · itemsize
burada:
  • neksen sayısı (ndim)
  • dₖk. eksen boyunca uzunluk (shape içindeki bir değer)
  • itemsizebir elemanın bayt cinsinden boyutu: float64 ve int64 için 8, float32 ve int32 için 4, bool ve int8 için 1

Şekli (2, 3) olan m için size = 2 · 3 = 6. temps için nbytes = 4 · 8 = 32 bayt.

dtypeBaytAralık / hassasiyetNerede kullanılır
bool1True / Falsemaskeler, bayraklar
uint810 … 255görüntü pikselleri
int324yaklaşık ±2,1 · 10⁹sayaçlar, indeksler
int648yaklaşık ±9,2 · 10¹⁸büyük tam sayılar
float324~7 anlamlı basamaksinir ağları, GPU
float648~15–16 anlamlı basamakondalıklı sayılar için varsayılan tür

Bir dizinin tüm elemanları aynı türde olmalıdır. Türler karıştığında NumPy hepsini “en geniş” türe çevirir: tam sayılar ve ondalıklı sayılar birlikte float64 verir, sayılar ve metinler birlikte metin verir. astype türü açıkça değiştirir; ondalıklı sayıyı tam sayıya çevirirken ondalık kısım yuvarlanmaz, yalnızca 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)
▸ Beklenen çıktı
[1.  2.  3.5]
['1' '2' '3']
[ 1 -1]
[-56 -16]

Dizi oluşturmak

FonksiyonNe oluşturur
np.array(data)bir listeden ya da iç içe listelerden dizi
np.zeros(shape), np.ones(shape), np.full(shape, v)0, 1 ya da v ile doldurulmuş dizi
np.arange(start, stop, step)range gibi adımlı bir dizi; stop dahil değildir
np.linspace(start, stop, num)eşit aralıklı num nokta; iki uç da dahildir
np.eye(n)n × n birim matris
np.random.default_rng(seed)rastgele sayı üreteci
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))
▸ Beklenen çıktı
[[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 noktaları arasındaki adım
  • narange dizisindeki eleman sayısı
  • ⌈ ⌉yukarı yuvarlama (tavan)

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

Ondalıklı adımlı arange konusunda dikkatli ol: 0,1 ikilik sistemde tam olarak gösterilemez ve yuvarlama hatası son elemanın diziye girip girmeyeceğini değiştirebilir. Aşağıda stop = 1.3 olmasına rağmen 1,3 diziye dahil oldu:

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))
▸ Beklenen çıktı
10
[1.  1.1 1.2 1.3]
[1.  1.1 1.2 1.3]

Rastgele sayı üretmenin modern yolu bir üreteç oluşturmaktır: rng = np.random.default_rng(42). Buradaki 42 tohumdur (seed): aynı tohumla üreteç her seferinde aynı diziyi verir. Bilimsel çalışmada bu önemlidir; bir meslektaşın kodunu çalıştırıp aynı sonucu alabilmelidir. integers(a, b) üst sınırı dahil etmez, normal(loc, scale) normal dağılımdan, random() ise [0; 1) aralığından sayılar döndürür. Eski kodlarda göreceğin np.random.seed ve np.random.rand yerine yeni kodda üreteç kullan.

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))
▸ Beklenen çıktı
[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 zar atışı, ortalama boyu 170 cm olan dört kişinin rastgele boyları ve 2 × 3 boyutlu rastgele bir matris. Kodu yeniden çalıştırırsan sonuç aynı kalır.

İndeksleme, dilimleme ve mantıksal maskeler

Tek boyutlu bir dizi liste gibi indekslenir: a[0], a[-1], a[2:5], a[::2]. İki boyutlu dizide indeksler virgülle ayrılır: m[satır, sütun]. İki nokta : “bu eksendeki her şey” anlamına gelir: m[:, 1] ikinci sütun, m[1] ikinci satırdır. Dilimler her eksende ayrı çalışır; negatif adım ise sırayı tersine ç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])
▸ Beklenen çıktı
[[ 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 elemanı 3 satır ve 4 sütuna yerleştirir (ayrıntılar bir sonraki derste). m[::2, ::-1] her ikinci satırı, sütunları ters sırada alır.
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)
▸ Beklenen çıktı
[100   2   3   4]
[5 6 7 8] [-1  6  7  8]

Bir diziye uygulanan karşılaştırma her eleman için True ya da False döndürür; buna mantıksal maske denir. Maskeyi indeks olarak verirsen yalnızca True olan elemanlar seçilir. True 1, False 0 sayıldığı için mask.sum() koşula uyan eleman sayısını, mask.mean() ise bunların oranını verir. np.where(koşul, a, b) her eleman için “eğer…, o zaman a, değilse b” seçimini tek işlemde yapar. Aşağıda bir haftanın öğle sıcaklıkları 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))
▸ Beklenen çıktı
[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 elemanların indekslerini döndürür: 0'dan sayınca 2, 3 ve 4 numaralı günler. Son satır 30'un üzerindeki değerleri 30 ile değiştirir.
Örnek 1: indeksler ve eksenler elle

a = np.arange(12).reshape(3, 4) için kodu çalıştırmadan bul: a) a[1:, ::2]; b) a.sum(axis=0) ve a.sum(axis=1) ile bunların şekilleri; c) (a % 5 == 0).sum().

Çözümü göster
a = [[0 1 2 3], [4 5 6 7], [8 9 10 11]].
a) 1: 1 ve 2 numaralı satırları, ::2 0 ve 2 numaralı sütunları alır: [[4 6], [8 10]].
b) axis=0 satırları “sıkıştırır”, her sütunun toplamı kalır: [0+4+8, 1+5+9, 2+6+10, 3+7+11] = [12 15 18 21], şekil (4,).
axis=1 her satırın toplamını verir: [6 22 38], şekil (3,).
c) 5'e bölünen elemanlar 0, 5 ve 10'dur; maskede 3 tane True var: cevap 3.

Özetleme ve axis parametresi

sum, mean, min, max, std, argmax, cumsum gibi fonksiyonlar çok sayıda sayıyı tek bir sayıya ya da daha küçük bir diziye “indirger”; buna özetleme (aggregation) denir. axis verilmezse hesap dizinin tamamı üzerinden yapılır. axis=0 birinci eksen boyunca (satırlar boyunca aşağı) hesaplar ve her sütun için bir sonuç verir; axis=1 sütunlar boyunca hesaplar ve her satır için bir sonuç verir. Aşağıda 4 öğrencinin (satırlar) matematik, fizik ve kimya (sütunlar) puanları 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])
▸ Beklenen çıktı
(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]
Derslerin ortalamaları 79,25; 79,75 ve 81; öğrencilerin ortalamaları 85, 74, 92 ve 69'dur. argmax(axis=0) her derste en iyi öğrencinin indeksini verir: matematik ve kimyada 2 numaralı, fizikte 0 numaralı öğrenci.
x̄ = (1/n) · ∑ xᵢ σ = √( ∑ (xᵢ − x̄)² / (n − ddof) )x̄ = (1/n) · ∑ xᵢ σ = √( ∑ (xᵢ − x̄)² / (n − ddof) )
burada:
  • x̄aritmetik ortalama (mean)
  • ndeğer sayısı
  • σstandart sapma (std): değerlerin ortalamadan tipik olarak ne kadar uzaklaştığı
  • ddof0 — ana kütle için (NumPy'da varsayılan), 1 — örneklem için (yansız varyans)

np.std varsayılan olarak n'ye böler; istatistik kitapları ve pandas'taki Series.std ise n − 1'e böler. Aynı sonucu almak için ddof=1 ver.

Örnek 2: standart sapma elle

x = [2, 4, 4, 4, 5, 5, 7, 9]. np.std(x) ve np.std(x, ddof=1) ne döndürür?

Çözümü göster
x̄ = 40 / 8 = 5.
Ortalamadan sapmaların kareleri: 9, 1, 1, 1, 0, 0, 4, 16; toplamı 32.
ddof = 0: σ² = 32 / 8 = 4, σ = 2.
ddof = 1: s² = 32 / 7 ≈ 4,571, s ≈ 2,138.
n büyüdükçe iki cevap arasındaki fark küçülür.

Bunlar nerede işine yarayacak? pandas tablolarının sütunları NumPy dizileridir; scikit-learn veriyi (n × d) şeklinde bir dizi olarak alır; görüntü işleme, sinyaller, finansal zaman serileri ve fizik modelleri hep diziler üzerindeki işlemlerdir. Bir sonraki derste döngüleri tamamen vektörleştirilmiş kodla değiştirmeyi ve doğrusal cebiri öğreneceksin.

Alıştırma

sales dizisinde küçük bir kafenin 4 haftalık satışları var (satırlar haftalar, sütunlar pazartesiden pazara günler). Ayrı satırlarda yazdır: 1) her haftanın toplam satışı; 2) 4 hafta boyunca en çok satış yapılan hafta gününün indeksi (0 = pazartesi); 3) satışın 100'ü aştığı gün sayısı. Döngü kullanma.

Alıştırma · 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
▸ Beklenen çıktı
[725 760 750 761]
5
12
Alıştırma

Sensör ölçümlerindeki negatif değerler hatadır. 1) np.where ile negatif değerleri 0.0 ile değiştirip yeni diziyi yazdır; 2) ilk dizide 10'dan büyük ölçümlerin ortalamasını 1 ondalık basamağa yuvarlayarak yazdır.

Alıştırma · 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
▸ Beklenen çıktı
[12.5  0.   8.4 15.1  0.  20.3  9.9 11. ]
14.7

Önemli noktalar

  • ndarray aynı türden elemanları bellekte art arda saklar; temel öznitelikleri ndim, shape, size ve dtype'tır, nbytes = size · itemsize.
  • arange stop değerini dahil etmez; ondalıklı adımlar için iki ucu da içeren linspace daha güvenlidir.
  • Tekrarlanabilir rastgele sayılar için np.random.default_rng(seed) üretecini kullan.
  • Dilim bir görünümdür: onu değiştirmek asıl diziyi değiştirir; bağımsız kopya için .copy().
  • Maskeleri &, |, ~ ve parantezlerle birleştir; mask.sum() sayıyı, mask.mean() oranı verir.
  • axis=k, k eksenini sonucun şeklinden çıkarır; np.std varsayılan olarak ddof=0 kullanır.

Kendini test et

10 soru. Her doğru cevap XP kazandırır.

1 / 10
np.zeros((3, 4)).sum(axis=0) sonucunun şekli nedir?