Bu bölümde öncelikle kullanılabilecek veri tipleri ve yapısal veri hakkında bilgi verilecektir. Ardından temel metotlar, property’ler, temel işlemler, evrensel fonksiyonlar ve array işlemleri hakkında basit örneklerle gösterilecektir.
02.01. Veri tipleri (Data Types)
Numpy, Python’dan farklı olarak 16 farklı veri tipini destekler. (_bool, int_, intc, intp, int8, int16, int32, int64, uint8, uint16, uint32, uint64, float_, float16, float32, float64, complex_, complex64, complex128)
“_” ile biten veri tipleri o veri tipinin en yüksek değerinin kısa halidir. Örneğin float_ için float64 değeridir. Ayrıca int8, int16, int32, int64 yerine sırasıyla ‘i1’, ‘i2′,’i4’ vb. string’leri de kullanılabilir.
#int8, int16, int32, int64 can be replaced by equivalent string ‘i1’, ‘i2′,’i4’, etc.
1 2 3 4 |
dt = np.dtype(np.int32) print(dt) dt = np.dtype('i4') print(dt) |
1 2 |
int32 int32 |
Yapısal veri tipleri de yapılabilir. Yapısallık demek veri tipinin yanına isminin yazılmasıdır. Örneğin,
1 2 3 4 5 6 7 8 9 10 11 12 13 |
dt = np.dtype([('yas',np.int8)]) print(dt) dt = np.dtype([('yas',np.int8)]) a = np.array([(10,),(20,),(30,)], dtype = dt) print(a) dt = np.dtype([('yas',np.int8)]) a = np.array([(10,),(20,),(30,)], dtype = dt) print(a['yas']) ogrenci = np.dtype([('name','S20'), ('yas', 'i1'), ('marks', 'f4')]) print(ogrenci) ogrenci = np.dtype([('name','S20'), ('yas', 'i1'), ('marks', 'f4')]) a = np.array([('abc', 21, 50),('xyz', 18, 75)], dtype = ogrenci) print(a) |
1 2 3 4 5 |
[('yas', 'i1')] [(10,) (20,) (30,)] [10 20 30] [('name', 'S20'), ('yas', 'i1'), ('marks', '<f4')] [(b'abc', 21, 50.) (b'xyz', 18, 75.)] |
Şimdi bir kaç property ve metodu daha inceleyelim.
02.02. Temel metotlar ve property’ler
Bu bölümü okumadan önce property ve değişken kavramlarının farkını bilmeyen öğrenciler, öncelik linkteki yazıyı okumalarını tavsiye ederim. Property kelimesinin de Türkçe’ye çevrildiğinde anlamını yitirdiği için property şeklinde kullanacağım. Öncelikle arange ve reshape metotlarını ile bir dizi oluşturacağız. Ardından shape, ndim, dtype.name, itemsize property’leri sonuçlarını inceleyeceğiz.
1 2 3 4 5 6 7 |
a = np.arange(15).reshape(3, 5) #arange sıralı bir dizi oluşturur, reshape bu diziye tekrar şekil verir: 3x5'lik print(a) print(a.shape) print(a.ndim) #boyut(dimension) sayısı, shape'deki eleman sayısı print(a.dtype.name) #veri tipi, dikkat edildiyse veri tipi verilmedi ama otomatik olarak belirlenir print(a.itemsize) #öğe boyutu, bit değeri / 8, örneğin int64 için 64 / 8 print(type(a)) #veri tipi ama a nesnesinin, öğelerin değil |
1 2 3 4 5 6 7 8 |
[[ 0 1 2 3 4] [ 5 6 7 8 9] [10 11 12 13 14]] (3, 5) 2 int32 4 <class 'numpy.ndarray'> |
arange komutu aslında range komutunun modifiye edilmiş halidir. Python’da range kullanımı hatırlayacak olursak başlangıç, bitiş ve adım değerleri parametre olarak alabiliyordu. Bitiş değeri zorunlu iken başlangıç ve adım değerleri seçimlik idi. Ayrıca, başlangıç ve adım belirtilmediğinde sırasıyla 0 ve 1 değerlerini alıyordu. Otomatik dizi oluşturma diğer bir metot “linspace” metodudur. Örneğin,
1 2 |
a = np.linspace( 0, 2, 9 ) print(a) |
1 |
[0. 0.25 0.5 0.75 1. 1.25 1.5 1.75 2. ] |
linspace ilk iki parametre başlangıç ve bitiş değerlerini verirken, son parametre ise eleman sayısını verir. Bu eleman sayısına göre sayılar ardışık olarak oluşturulur. Ayrıca linspace ile oluşan tüm değerleri tek bir fonksiyondan geçirip, tekrar hesaplatabilirsiniz. Örneğin,
1 2 3 4 5 |
import math x = np.linspace( 0, 2*math.pi, 10 ) # bir çok noktayı, tek fonksiyondan geçirebilirsiniz print(x) f = np.sin(x) print(f) |
1 2 3 4 5 |
[0. 0.6981317 1.3962634 2.0943951 2.7925268 3.4906585 4.1887902 4.88692191 5.58505361 6.28318531] [ 0.00000000e+00 6.42787610e-01 9.84807753e-01 8.66025404e-01 3.42020143e-01 -3.42020143e-01 -8.66025404e-01 -9.84807753e-01 -6.42787610e-01 -2.44929360e-16] |
Diğer bir yaratma yöntemi logspace’tir. İsminden de anlaşılacağı gibi düzenli bir log havuzu oluşturma için kullanılır. Örneğin,
1 2 |
a = np.logspace(1,10,num = 10, base = 2) print(a) |
1 |
[ 2. 4. 8. 16. 32. 64. 128. 256. 512. 1024.] |
base’in defult değeri 10’dur. Ancak ben burada iki tabanında oluşturdum. Bu örneklerde metotlar basitçe verilmiştir. Bu metotların birçok parametresi olduğunu unutmayalım.
Büyük bir array görüntülerken otomatik olarak “…” ile array görüntüsü azaltılır. Örneğin,
1 2 |
print(np.arange(10000)) print(np.arange(10000).reshape(100,100)) |
1 2 3 4 5 6 7 8 |
[ 0 1 2 ... 9997 9998 9999] [[ 0 1 2 ... 97 98 99] [ 100 101 102 ... 197 198 199] [ 200 201 202 ... 297 298 299] ... [9700 9701 9702 ... 9797 9798 9799] [9800 9801 9802 ... 9897 9898 9899] [9900 9901 9902 ... 9997 9998 9999]] |
Tüm değerleri görmek isterseniz setprintoption property kapatabilirsiniz. Örneğin,
1 |
np.set_printoptions(threshold=np.nan) |
Bu durumdaki çıktıları vermiyorum 🙂
02.03. Temel işlemler
Aritmetiksel operatörleri direkt dizilerde kullanabilirsiniz. Örneğin,
1 2 3 4 5 6 |
a = np.array( [20,30,40,50] ) b = np.arange( 4 ) c = a-b print(a) print(b) print(c) |
1 2 3 |
[20 30 40 50] [0 1 2 3] [20 29 38 47] |
Ancak, matrix çarpımı yaparsanız sonuç yanlış olacaktır. Bu durumda matrix çarpımı için @ veya dot metodu kullanılır.
1 2 3 4 5 6 7 |
a = np.array( [[1,1],[0,1]] ) b = np.array( [[2,0],[3,4]] ) print(a) print(b) print(a*b) print(a@b) print(a.dot(b)) |
1 2 3 4 5 6 7 8 9 10 |
[[1 1] [0 1]] [[2 0] [3 4]] [[2 0] [0 4]] [[5 4] [3 4]] [[5 4] [3 4]] |
Bu arada += and *= kullanarak mevcut bir array üzerine de sonuçlar yazılabilir.
1 2 3 4 5 6 7 8 |
a = np.ones((2,3), dtype=int) b = np.random.random((2,3)) print(a) print(b) a *= 3 print(a) b += a print(b) |
1 2 3 4 5 6 7 8 |
[[1 1 1] [1 1 1]] [[0.26302162 0.65924625 0.67755421] [0.06203166 0.2622462 0.09491851]] [[3 3 3] [3 3 3]] [[3.26302162 3.65924625 3.67755421] [3.06203166 3.2622462 3.09491851]] |
Ancak a += b hata verir. Çünkü Numpy float + int otomatik float’a çevirebilir ama int + float tekrar bir int içine atamaz. Örneğin,
1 |
a += b |
1 2 3 4 5 6 |
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) <ipython-input-19-294cacd62d6f> in <module>() ----> 1 a += b TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int32') with casting rule 'same_kind' |
Python değişkenler konusunda esnek olsa da Numpy’de veri tiplerine ve dizi boyutlarına dikkat etmeniz gerekmektedir. Matris birleştirme yapabilir, hatta complex bir matris oluşturabiliriz. Örneğin,
1 2 3 4 5 6 7 8 9 |
import math a = np.ones(3, dtype=np.int32) b = np.linspace(0,math.pi,3) c = a+b d = np.exp(c*1j) print(a) print(b) print(c) print(d) |
1 2 3 4 |
[1 1 1] [0. 1.57079633 3.14159265] [1. 2.57079633 4.14159265] [ 0.54030231+0.84147098j -0.84147098+0.54030231j -0.54030231-0.84147098j] |
Numpy, array üzerinde toplama (sum), minimum (min) veya maksimum (max) gibi işlemler rahat yapılır.
1 2 3 4 5 |
a = np.random.random((2,3)) print(a) print(a.sum()) print(a.min()) print(a.max()) |
1 2 3 4 5 |
[[0.82469044 0.80951062 0.05916798] [0.921408 0.168077 0.49320159]] 3.276055633096906 0.05916798313288285 0.9214080012540528 |
axis parametresi ile satır veya sütunlar üzerine işlem yapabilirsiniz. Örneğin,
1 2 3 4 5 |
b = np.arange(12).reshape(3,4) print(b) print(b.sum(axis=0)) #sütunları toplar print(b.sum(axis=1)) #satırları toplar print(b.cumsum(axis=1)) #her satırı kümülatif toplar |
1 2 3 4 5 6 7 8 |
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [12 15 18 21] [ 6 22 38] [[ 0 1 3 6] [ 4 9 15 22] [ 8 17 27 38]] |
02.04. Evrensel fonksiyonlar
Numpy sin, cos, exp ve benzeri bilinen matematiksel fonksiyonlar için metotlar sağlar. Bu fonksiyonlara evrensel fonksiyonlar (ufunc) adı verilir. Bu metotlar bir array’dan fonksiyon ile başka bir array’a sonuç olarak aktarılır. Örneğin,
1 2 3 4 5 6 7 |
a = np.arange(3) print(a) print(np.exp(a)) print(np.sqrt(a)) b = np.array([2., -1., 4.]) c = np.add(a, b) print(c) |
1 2 3 4 |
[0 1 2] [1. 2.71828183 7.3890561 ] [0. 1. 1.41421356] [2. 0. 6.] |
Diğer fonksiyonlar: all, any, apply_along_axis, argmax, argmin, argsort, average, bincount, ceil, clip, conj, corrcoef, cov, cross, cumprod, cumsum, diff, dot, floor, inner, inv, lexsort, max, maximum, mean, median, min, minimum, nonzero, outer, prod, re, round, sort, std, sum, trace, transpose, var, vdot, vectorize, where…
02.05. Array işlemleri
Tek boyutlu ve çok boyutlu bir array’lerde verilere ulaşma, belli bir veri grubunu çekme ve array üzerinde dolaşma örneklerine bakalım.
1 2 3 4 5 6 7 |
a = np.arange(10)**3 print(a) print(a[2]) print(a[2:]) #2'den sonraki tüm elemanlar print(a[3:5]) #3 ile 5 arası elamanlar a[2] = 5 #veri güncelleme print(a) |
1 2 3 4 5 |
[ 0 1 8 27 64 125 216 343 512 729] 8 [ 8 27 64 125 216 343 512 729] [27 64] [ 0 1 5 27 64 125 216 343 512 729] |
Python List konusunu bilen bir öğrenci için yukarıdaki örnekler çok tanıdık gelmiştir. Güncelleme işlemi klasik bir array’da olduğu gibidir. Numpy toplu güncellemeye de destek verir. Şöyle ki:
1 2 3 4 |
a[:6:2] = -1000 # 0'dan başlayarak 2 şer 2 şer 6'ya olan index'lere -1000 sayısını arttır. print(a) a = a[ : :-1] # Array'i terse çevir print(a) |
1 2 |
[-1000 1 -1000 27 -1000 125 216 343 512 729] [ 729 512 343 216 125 -1000 27 -1000 1 -1000] |
Tek boyutlu bir dizi aşağıdaki şekilde dolaşabiliriz.
1 2 |
for i in a: print(i*(1/3)) |
1 2 3 4 5 6 7 8 9 10 |
243.0 170.66666666666666 114.33333333333333 72.0 41.666666666666664 -333.3333333333333 9.0 -333.3333333333333 0.3333333333333333 -333.3333333333333 |
Şimdi çok boyutlu dizilere bakalım. Çok boyutlu bir dizi manuel de oluştur, ancak farklı bir kullanım olması için öncelikle bir metot ile oluşturacağız.
1 2 3 4 5 |
def f(x,y): return 10*x+y a = np.fromfunction(f,(5,4),dtype=int) print(a) |
1 2 3 4 5 |
[[ 0 1 2 3] [10 11 12 13] [20 21 22 23] [30 31 32 33] [40 41 42 43]] |
fromfunction metodu f fonksiyonuna sayıları gönderir. (5, 4) dizinin boyutunu verir. Örneğin çok boyutlu dizideki [1, 1] değeri f fonksiyonu ile hesaplandığında 10*1+1 ile 11 değeri bulunur.
1 2 3 4 5 6 |
print(a[1, 1]) print(a[0:5, 1]) #ikinci kolondaki her satır değeri, 0:5 olduğu için tüm satırları alır print(a[ : ,1]) #yukarıdaki ile aynı değeri döndürür print(a[1:3, : ]) #2. ve 3. satırın tüm elemanları print(a[-1]) #tersten ilk row print(a[-1, : ]) #yukarıdakinin aynısı |
1 2 3 4 5 6 7 |
11 [ 1 11 21 31 41] [ 1 11 21 31 41] [[10 11 12 13] [20 21 22 23]] [40 41 42 43] [40 41 42 43] |
Şimdi 3 boyutlu dizi yapalım ama bu kez manuel tanımlayalım.
1 2 3 4 5 6 7 |
a = np.array( [[[ 0, 1, 2], # 3 boyutlu bir array, parantezlere dikkat [ 10, 12, 13]], [[100,101,102], [110,112,113]]]) print(a.shape) print(a[1,...]) #a[1,:,:] ya da a[1] aynı print(a[...,2]) #a[:,:,2] |
1 2 3 4 5 |
(2, 2, 3) [[100 101 102] [110 112 113]] [[ 2 13] [102 113]] |
Şimdi de bir döngü ile verileri dolaşalım. Örneğin,
1 2 |
for element in a: print(element) |
1 2 3 4 |
[[ 0 1 2] [10 12 13]] [[100 101 102] [110 112 113]] |
Tüm elemanları teker teker dolaşmak “flat” özelliği kullanılabilir. Örneğin,
1 2 |
for element in a.flat: print(element) |
1 2 3 4 5 6 7 8 9 10 11 12 |
0 1 2 10 12 13 100 101 102 110 112 113 |