- ndarray özniteliklerini (
ndim,shape,size,dtype) açıklamak ve bir dizinin bellekte kapladığı yeri hesaplamak arange,linspace,zerosve tohumludefault_rngile diziler oluşturmak- İndeks, dilim ve mantıksal maskelerle veri seçmek, görünümü kopyadan ayırt etmek
axisparametresiyle 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.
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.
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ı.- neksen sayısı (
ndim) - dₖk. eksen boyunca uzunluk (
shapeiçindeki bir değer) - itemsizebir elemanın bayt cinsinden boyutu:
float64veint64için 8,float32veint32için 4,boolveint8için 1
Şekli (2, 3) olan m için size = 2 · 3 = 6. temps için nbytes = 4 · 8 = 32 bayt.
| dtype | Bayt | Aralık / hassasiyet | Nerede kullanılır |
|---|---|---|---|
bool | 1 | True / False | maskeler, bayraklar |
uint8 | 1 | 0 … 255 | görüntü pikselleri |
int32 | 4 | yaklaşık ±2,1 · 10⁹ | sayaçlar, indeksler |
int64 | 8 | yaklaşık ±9,2 · 10¹⁸ | büyük tam sayılar |
float32 | 4 | ~7 anlamlı basamak | sinir ağları, GPU |
float64 | 8 | ~15–16 anlamlı basamak | ondalı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.
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
| Fonksiyon | Ne 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 |
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
linspacenoktaları arasındaki adım - n
arangedizisindeki 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:
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.
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]]
İ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.
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.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:
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.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Çözümü gizle
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:
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]
argmax(axis=0) her derste en iyi öğrencinin indeksini verir: matematik ve kimyada 2 numaralı, fizikte 0 numaralı öğrenci.- 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.
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Çözümü gizle
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.
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.
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
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.
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,sizevedtype'tır, nbytes = size · itemsize. arangestopdeğerini dahil etmez; ondalıklı adımlar için iki ucu da içerenlinspacedaha 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.stdvarsayılan olarakddof=0kullanır.
Kendini test et
10 soru. Her doğru cevap XP kazandırır.
np.zeros((3, 4)).sum(axis=0) sonucunun şekli nedir?