pandas
Python programlama dili için yazılmış, BSD-lisanslı açık kaynak kodlu, yüksek performanslı, kolay kullanılabilen veri yapıları ve analiz araçları sağlayan bir kütüphanedir (pandas dokümantasyonu). Üzerine kurulu olduğu, bir yaygın sayfa yapısına benzer, sütunların isimlendirildiği veri çerçevesi nesnesi (ing. DataFrame
) sayesinde veriyle kolay ve hızlı etkileşim sağlar.
Seriler (series
) etiketlendirlmiş birer bir boyutlu (1D) dizidir. Yapısı sözlük (dictionary) yapısına benzer, tıpkı numpy dizileri gibi sabit bir uzunluğa sahiptir. Değer almayan ya da 'N/A', 'NaN', '-' gibi nümerik olmayan değerler alan sütunların yönetimine de olanak sağlar. Numpy ya da Python'un standart işlem ya da fonksiyonlarının üzerinde kullanılabildiği bir yapıdır. Örneğin sözlüklerde (dictionary) bu işlem ve fonksiyonların çok büyük bir bölümü kullanılamaz. pandas modülünün üzerine kurulu olduğu DataFrame
yapısının temelinde pandas serileri vardır. pandas serileri temel olarak veri çerçevelerinin sütunları olarak kullanılabilmekle birlikte kendi başlarına veri yapıları olarak da kullanılabilirler.
İşe bir pandas.Series
nesnesi oluşturarak başlayalım.
import pandas as pd
import numpy as np
gzgn_kutleler = pd.Series([0.330, 4.87, 5.97, 0.642, 1898, 568, 86.8, 102], \
index=['merkur', 'venus', 'dunya','mars','jupiter', 'saturn', 'uranus', 'neptun'], \
name="gezegenler")
print(gzgn_kutleler)
merkur 0.330 venus 4.870 dunya 5.970 mars 0.642 jupiter 1898.000 saturn 568.000 uranus 86.800 neptun 102.000 Name: gezegenler, dtype: float64
Görüldüğü gibi gzgn_kutleler pandas serisini oluşturmak üzere bir listeden sağlanan etiketler (labels
ya da index
) her bir gezegeni, değerler ise yine bir listeden sağlanan ($10^{24}$ kg cinsinden) kütle değerlerini göstermektedir. Değerleri bir numpy dizisi gibi itere edilebilir (iterable) başka bir değişken türünden de sağlamak mümkündür. Bu anlamda, pandas modülünün Series
nesnesi serbest olarak indekslenmiş birer numpy
dizisi gibi de düşünülebilir.
pandas serileri etiketsiz (ya da indekssiz) başlatılabileceği gibi, ki bu durumda indeksler 0'dan başlanarak tam sayılarla numaralandırılır, bir sözlük (dictionary) değişkeni üzerinden de tanımlanabilir. Yapıları nedeniyle Pandas series
nesnesi, özelleştirilmiş birer dictionary
(sözlük) nesnesi gibi de düşünülebilir. Her bir indeks söz konusu seride bir satırdaki değere karşılık gelmektedir.
import numpy as np
s1 = pd.Series(np.random.randn(5)*10)
print(s1)
0 -14.551054 1 -14.167069 2 -3.775805 3 6.826160 4 -3.045792 dtype: float64
yldz_mV = {'Sirius' : -0.5, 'Vega' : 0.0, 'Proxima' : 13.6}
print(type(yldz_mV), yldz_mV)
yldz_mV = pd.Series((yldz_mV))
print(yldz_mV)
print(type(yldz_mV))
<class 'dict'> {'Sirius': -0.5, 'Vega': 0.0, 'Proxima': 13.6} Sirius -0.5 Vega 0.0 Proxima 13.6 dtype: float64 <class 'pandas.core.series.Series'>
pd.Series(yldz_mV, index=['Vega', 'Sirius', 'Altair', 'Proxima'])
Vega 0.0 Sirius -0.5 Altair NaN Proxima 13.6 dtype: float64
İstendiği takdirde bir pandas serisine isim (name) de atanabilir. Bu amaçla serinin name
ya da rename
öznitelikleri kullanılır. Bu isim bu seri, bir tabloya (veri çerçevesine) sütun yapılmak istendiğinde sütun ismi olarak da kullanılabilecektir.
print(yldz_mV.name)
None
yldz_mV.name = "yildizlar"
print(yldz_mV)
Sirius -0.5 Vega 0.0 Proxima 13.6 Name: yildizlar, dtype: float64
Tıpkı bir numpy dizisi gibi pandas series
nesnesi üzerinde işlemler yapılabilir ve fonksiyonlar uygulanabilir, indeksleme ve dilimleme özellikleri kullanılabilir.
print(gzgn_kutleler[::2])
merkur 0.33 dunya 5.97 jupiter 1898.00 uranus 86.80 Name: gezegenler, dtype: float64
print(gzgn_kutleler > gzgn_kutleler['dunya'])
merkur False venus False dunya False mars False jupiter True saturn True uranus True neptun True Name: gezegenler, dtype: bool
print(gzgn_kutleler[gzgn_kutleler < gzgn_kutleler['uranus']])
merkur 0.330 venus 4.870 dunya 5.970 mars 0.642 Name: gezegenler, dtype: float64
print(yldz_mV[1:-1])
print("-----------------")
print(yldz_mV[yldz_mV > yldz_mV.median()])
Vega 0.0 Name: yildizlar, dtype: float64 ----------------- Proxima 13.6 Name: yildizlar, dtype: float64
y1 = 'Vega'
y2 = 'Proxima'
print("{:s} ile {:s}'nin aki oranlari {:g}.".\
format(y1, y2, 10**(-0.4*(yldz_mV[y1]-yldz_mV[y2]))))
Vega ile Proxima'nin aki oranlari 275423.
'Betelgeuse' in yldz_mV
False
print("Verilen yildizlarin ortalama parlakligi: {:g}, standart sapmasi: {:g}".\
format(yldz_mV.mean(), yldz_mV.std()))
Verilen yildizlarin ortalama parlakligi: 4.36667, standart sapmasi: 8.00021
s2 = pd.Series(np.random.randn(5)*2.5)
print("s2: \n", s2)
print("s2 + s2: \n" , s2 + s2)
print("s2^2: \n", s2**2)
s2: 0 2.516031 1 4.025176 2 -2.235994 3 -2.221468 4 -1.036793 dtype: float64 s2 + s2: 0 5.032062 1 8.050352 2 -4.471989 3 -4.442936 4 -2.073587 dtype: float64 s2^2: 0 6.330413 1 16.202043 2 4.999671 3 4.934920 4 1.074941 dtype: float64
Bu işlemlerde her iki tarafta aynı başlıkların (indekslerin ya da etiketlerin) olmaması sorunu da pandas tarafından etkin bir şekilde yönetilir.
a = s2[1:]
print(a)
1 4.025176 2 -2.235994 3 -2.221468 4 -1.036793 dtype: float64
s2[1:] + s2[:-2]
0 NaN 1 8.050352 2 -4.471989 3 NaN 4 NaN dtype: float64
print(yldz_mV.name)
yldz_mV = yldz_mV.rename('mV')
print(yldz_mV.name)
yildizlar mV
pandas serilerine (series) yeni seriler append
concat
fonksiyonuyla eklenir. Veriçerçevelerinin her seferinde tüm verilerin arka arkaya eklenerek yeniden oluşturulması sebebiyle append
metodu pandas 1.4.0
versiyonundan itibaren kullanımdan kaldırılmıştır.
pd.__version__
'1.4.3'
print(gzgn_kutleler)
yeni_cisimler = {'pluto':0.0146, 'ay':0.073}
print("------------")
gzgn_kutleler = pd.concat([gzgn_kutleler,pd.Series(yeni_cisimler)],axis=0,sort=False)
print(gzgn_kutleler)
merkur 0.330 venus 4.870 dunya 5.970 mars 0.642 jupiter 1898.000 saturn 568.000 uranus 86.800 neptun 102.000 Name: gezegenler, dtype: float64 ------------ merkur 0.3300 venus 4.8700 dunya 5.9700 mars 0.6420 jupiter 1898.0000 saturn 568.0000 uranus 86.8000 neptun 102.0000 pluto 0.0146 ay 0.0730 dtype: float64
print("Saturn'un kutlesi, {:.4f} Jupiter kutlesidir.".format(gzgn_kutleler['saturn'] / gzgn_kutleler['jupiter']))
Saturn'un kutlesi, 0.2993 Jupiter kutlesidir.
Pandas serileri her ne kadar veri üzerinde çalışmak için etkin ve hızlı bir yol sağlasa da Pandas'ın asıl veri nesnesi veri çerçeveleridir (DataFrame
). Seriler çoğu zaman hızlı bir şekilde veri çerçeveleri oluşturmak üzere ve her veri çerçevesinin sütunları olarak kullanılırlar ve bir boyutludurlar, veri çerçeveleri ise tablolar ve yaygın sayfalar (spreadsheet) olarak düşünülebilir. Bu yapıları nedeniyle Pandas DataFrame
nesnelerini, özelleştirilmiş birer dictionary
(sözlük) nesnesi olarak da düşünmek mümkündür. Her bir indeks söz konusu veri çerçevesinde bir sütuna karşılık gelir.
Bir DataFrame
pek çok açıdan sütun ve satırların isimlerinin olduğu yaygın sayfalara benzer. Yapıları gereği iki boyutuludur (2D). Pandas'la veri analizi büyük ölçüde veri çerçevesi nesnesi üzerine kurulu olduğundan en sık kullanılan nesneler de DataFrame
nesneleridir.
Veri çerçeveleri
Dolayısı ile Güneş Sistemi gezegenlerinin bazı özelliklerini saklamak istediğimiz gzgn_kutleler
serisi gibi yapıları saklamak için DataFrame
daha esnek ve kolay analize olanak sağlayan bir yapı sağlar. Bu seri daha geniş ve gezegenlere ilişkin başka özelliklerin de saklandığı bir gezegenler
veri çerçevesinin bir sütununu oluşturabilir.
gezegenler = {'Mg' : gzgn_kutleler,
'Rg' : pd.Series([2439.5, 6052., 6378., 1737.5, 3396., 71492., 60268., 25559., 24764., 1185.],\
index=['merkur','venus','dunya', 'ay', 'mars', 'jupiter', 'saturn', 'uranus', 'neptun','pluto']),\
'Prot' : pd.Series([1407.6, -5832.5, 23.9, 655.7, 24.6, 9.9, 10.7, -17.2, 16.1, -153.3],\
index=['merkur','venus','dunya', 'ay', 'mars', 'jupiter', 'saturn', 'uranus', 'neptun','pluto']),\
'Porb' : pd.Series([88.0, 224.7, 365.2, 27.3, 687.0, 4331, 10747, 30589, 59800, 90560], \
index=['merkur','venus','dunya', 'ay', 'mars', 'jupiter', 'saturn', 'uranus', 'neptun','pluto'])}
gunes_sistemi = pd.DataFrame(gezegenler)
gunes_sistemi
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
ay | 0.0730 | 1737.5 | 655.7 | 27.3 |
dunya | 5.9700 | 6378.0 | 23.9 | 365.2 |
jupiter | 1898.0000 | 71492.0 | 9.9 | 4331.0 |
mars | 0.6420 | 3396.0 | 24.6 | 687.0 |
merkur | 0.3300 | 2439.5 | 1407.6 | 88.0 |
neptun | 102.0000 | 24764.0 | 16.1 | 59800.0 |
pluto | 0.0146 | 1185.0 | -153.3 | 90560.0 |
saturn | 568.0000 | 60268.0 | 10.7 | 10747.0 |
uranus | 86.8000 | 25559.0 | -17.2 | 30589.0 |
venus | 4.8700 | 6052.0 | -5832.5 | 224.7 |
Veri çerçeveleri pandas serileri kullanılarak oluşturulabileceği gibi listelerden, numpy dizilerinden veya sözlüklerden de oluşturulabilir.
# Sozlukler uzerinden veri cercevesi olusturma
veri = {
'ogrno' : ['05','12','23','04'],
'arasinav' : [35, 72, 60, 100],
'final' : [70, 43, 57, 82]
}
ders1 = pd.DataFrame(veri)
print(ders1)
ogrno arasinav final 0 05 35 70 1 12 72 43 2 23 60 57 3 04 100 82
# Listeler uzerinden veri cercevesi olusturma
sehirler = pd.DataFrame(data = [
['01', 'Adana', 'Kebap'],
['34', 'Istanbul', 'Kalabalik'],
['06', 'Ankara', 'Memurlar'],
['35', 'Izmir', 'Gevrek'],
['44', 'Malatya', 'Kayisi'],
['16', 'Bursa', 'Uludag']
], columns = ['Plaka', 'Sehir', 'Ozellik'])
print(sehirler)
Plaka Sehir Ozellik 0 01 Adana Kebap 1 34 Istanbul Kalabalik 2 06 Ankara Memurlar 3 35 Izmir Gevrek 4 44 Malatya Kayisi 5 16 Bursa Uludag
# Numpy dizileri uzerinden veri cercevesi olusturma
tarihler = pd.date_range('20220222', periods=5)
df = pd.DataFrame(np.random.randn(5, 4), index=tarihler, columns=list('ABCD'))
print(df)
A B C D 2022-02-22 1.357591 1.452445 -0.754914 0.987056 2022-02-23 -1.313615 2.401218 0.705444 2.341917 2022-02-24 0.383417 -1.181176 0.778811 -0.643517 2022-02-25 -1.325880 -0.112487 0.854269 -0.080190 2022-02-26 -1.172382 0.096121 0.241880 0.002872
# Birden fazla nesne turu kullanarak veri cercevesi olusturma
df2 = pd.DataFrame({'A': 1.,
'B': pd.Timestamp('20220222'),
'C': pd.Series(1, index=list(range(4)), dtype='float32'),
'D': np.array([3] * 4, dtype='int32'),
'E': pd.Categorical(["AST413", "AST415", "AST416", "AST515"]),
'F': 'Asterosismoloji'})
print(df2)
A B C D E F 0 1.0 2022-02-22 1.0 3 AST413 Asterosismoloji 1 1.0 2022-02-22 1.0 3 AST415 Asterosismoloji 2 1.0 2022-02-22 1.0 3 AST416 Asterosismoloji 3 1.0 2022-02-22 1.0 3 AST515 Asterosismoloji
Veri çerçevelerinin tamamını, bir bölümünü, bir sütununu, bir satırını ya da bir elemanını görüntülemek için pek çok fonksiyon bulunduğu gibi listelerde ve dizilerde geçerli dilimleme ve indeksleme seçenekleri de kullanılabilmektedir.
print("Tun Gunes Sistemi")
print(gunes_sistemi)
print("---------------------")
print("Veri cercevesindeki ilk 5 gezegen")
print(gunes_sistemi.head())
print("---------------------")
print("Veri cercevesindeki son 3 gezegen")
print(gunes_sistemi.tail(3))
print("---------------------")
print("Kutleler : ")
print(gunes_sistemi['Mg']*1e24)
print("Ortalama Kutle: {:g} kg".format(gunes_sistemi['Mg'].mean()*1e24))
print("----------------------")
Tun Gunes Sistemi Mg Rg Prot Porb ay 0.0730 1737.5 655.7 27.3 dunya 5.9700 6378.0 23.9 365.2 jupiter 1898.0000 71492.0 9.9 4331.0 mars 0.6420 3396.0 24.6 687.0 merkur 0.3300 2439.5 1407.6 88.0 neptun 102.0000 24764.0 16.1 59800.0 pluto 0.0146 1185.0 -153.3 90560.0 saturn 568.0000 60268.0 10.7 10747.0 uranus 86.8000 25559.0 -17.2 30589.0 venus 4.8700 6052.0 -5832.5 224.7 --------------------- Veri cercevesindeki ilk 5 gezegen Mg Rg Prot Porb ay 0.073 1737.5 655.7 27.3 dunya 5.970 6378.0 23.9 365.2 jupiter 1898.000 71492.0 9.9 4331.0 mars 0.642 3396.0 24.6 687.0 merkur 0.330 2439.5 1407.6 88.0 --------------------- Veri cercevesindeki son 3 gezegen Mg Rg Prot Porb saturn 568.00 60268.0 10.7 10747.0 uranus 86.80 25559.0 -17.2 30589.0 venus 4.87 6052.0 -5832.5 224.7 --------------------- Kutleler : ay 7.300000e+22 dunya 5.970000e+24 jupiter 1.898000e+27 mars 6.420000e+23 merkur 3.300000e+23 neptun 1.020000e+26 pluto 1.460000e+22 saturn 5.680000e+26 uranus 8.680000e+25 venus 4.870000e+24 Name: Mg, dtype: float64 Ortalama Kutle: 2.6667e+26 kg ----------------------
gunes_sistemi.info()
<class 'pandas.core.frame.DataFrame'> Index: 10 entries, ay to venus Data columns (total 4 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Mg 10 non-null float64 1 Rg 10 non-null float64 2 Prot 10 non-null float64 3 Porb 10 non-null float64 dtypes: float64(4) memory usage: 400.0+ bytes
print(gunes_sistemi.columns)
Index(['Mg', 'Rg', 'Prot', 'Porb'], dtype='object')
cols = [col for col in gunes_sistemi.columns]
gunes_sistemi[cols].dtypes
Mg float64 Rg float64 Prot float64 Porb float64 dtype: object
describe
metodu ile veri setinin bazı istatistiksel parametrelerini görmek ve veri seti hakkında hızlı bir yorumda bulunmak da mümkün olabilir.
print(gunes_sistemi.describe())
Mg Rg Prot Porb count 10.000000 10.00000 10.000000 10.00000 mean 266.669960 20327.10000 -385.450000 19741.92000 std 599.249294 25770.69571 1971.154887 31535.38816 min 0.014600 1185.00000 -5832.500000 27.30000 25% 0.408000 2678.62500 -10.425000 259.82500 50% 5.420000 6215.00000 13.400000 2509.00000 75% 98.200000 25360.25000 24.425000 25628.50000 max 1898.000000 71492.00000 1407.600000 90560.00000
Veri çerçevesini herhangi bir eksene göre sıralamak için sort_values
fonksiyonu kullanılır.
gunes_sistemi.sort_values(by='Rg')
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
pluto | 0.0146 | 1185.0 | -153.3 | 90560.0 |
ay | 0.0730 | 1737.5 | 655.7 | 27.3 |
merkur | 0.3300 | 2439.5 | 1407.6 | 88.0 |
mars | 0.6420 | 3396.0 | 24.6 | 687.0 |
venus | 4.8700 | 6052.0 | -5832.5 | 224.7 |
dunya | 5.9700 | 6378.0 | 23.9 | 365.2 |
neptun | 102.0000 | 24764.0 | 16.1 | 59800.0 |
uranus | 86.8000 | 25559.0 | -17.2 | 30589.0 |
saturn | 568.0000 | 60268.0 | 10.7 | 10747.0 |
jupiter | 1898.0000 | 71492.0 | 9.9 | 4331.0 |
İndeksleme ve dilimleme işlemleri tıpkı numpy
, list
, tuple
nesenlerinde ve pd.Series
nesnesinde yapıldığı şekliyle yapılabilir. Bunun dışındaki işlemler için:
df[col]
(ilgili sütundaki seriyi getirir)df.loc[label]
(ilgii satırdaki seriyi getirir)df.iloc[loc]
(ilgii satırdaki seriyi getirir)df[5:10]
(Veri çerçevesinin dilimlenmiş bölümünü getirir)df[kosul]
(Veri çerçevesinin koşula uyan bölümünü)yapıarı da kullanılabilir. Öncelikle numpy
dizilerindeki indeksleme tarzı indeksleme seçeneklerini gözden geçirelim.
gunes_sistemi[::2]
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
ay | 0.0730 | 1737.5 | 655.7 | 27.3 |
jupiter | 1898.0000 | 71492.0 | 9.9 | 4331.0 |
merkur | 0.3300 | 2439.5 | 1407.6 | 88.0 |
pluto | 0.0146 | 1185.0 | -153.3 | 90560.0 |
uranus | 86.8000 | 25559.0 | -17.2 | 30589.0 |
gunes_sistemi[-1:0:-2]
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
venus | 4.870 | 6052.0 | -5832.5 | 224.7 |
saturn | 568.000 | 60268.0 | 10.7 | 10747.0 |
neptun | 102.000 | 24764.0 | 16.1 | 59800.0 |
mars | 0.642 | 3396.0 | 24.6 | 687.0 |
dunya | 5.970 | 6378.0 | 23.9 | 365.2 |
İndekslemede tamsayı indekslere başvurarak verilerin yeri üzerinden yukarıdaki gibi indeksleme yapılabileeği gibi (ing. implicit indexes), Series
ve DataFrame
nesnelerinin indeksleri (satır isimleri olarak da düşünülebilir) olduğu düşüncesinden hareketle bu indeksler üzerinden de dilimleme ve indeksleme (ing. explicit indexes) yapılabilir.
gunes_sistemi['jupiter':'pluto']
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
jupiter | 1898.0000 | 71492.0 | 9.9 | 4331.0 |
mars | 0.6420 | 3396.0 | 24.6 | 687.0 |
merkur | 0.3300 | 2439.5 | 1407.6 | 88.0 |
neptun | 102.0000 | 24764.0 | 16.1 | 59800.0 |
pluto | 0.0146 | 1185.0 | -153.3 | 90560.0 |
Bu durumda özellikle tamsayı indeksler seçilerek kullanıcı tarafından oluşturulmuş veri çerçeveleri ve seriler üzerinde çalışılırken, kullanıcının belirlediği indekslerin mi yoksa verinin bulunduğu yerin indekslerinin mi geçerli olduğu gibi bir soru ortaya çıkar. Bunu basit bir örnekle görelim.
seri_tamindeks = pd.Series(['merkur', 'dunya', 'jupiter'], index=[1, 3, 5])
#Indeksleme yapilirken kullanici tanimli indeksler kullanilirken
print(seri_tamindeks[1])
print("---------------")
#Dilimlemede verinin yerine dayali indeksler kullanilir
print(seri_tamindeks[0:2])
merkur --------------- 1 merkur 3 dunya dtype: object
Bu karışıklığı önlemek için Pandas, bazı dizinleme şemalarını esas alan özel dizin oluşturucu özellikler (attributes
) sağlar. Bunları pandas nesneleri üzerinde tanımlı fonksiyonlar metotlar (methods
) olarak değil, o nesneye özel özellikler olarak düşünmek gerekir.
loc
özniteliği (attribute) her zaman kullanıcı tarafından verilen indekslere referans vermek için kullanılır.
# seri_tamindeks uzerinde bu kez kullanici indeksiyle veri secelim
print(seri_tamindeks.loc[5])
jupiter
# Gunes Sistemi veri cercevesi uzerinde
# Herhangi satir(lar)i indeksiyle secmek icin
gunes_sistemi.loc['jupiter']
Mg 1898.0 Rg 71492.0 Prot 9.9 Porb 4331.0 Name: jupiter, dtype: float64
Dilimlemede kullanıcı tanımlı indeksler üzerinden dilimleme yapılırken verilen aralığın her iki ucu da (sonu da!) dilimlememey dahil edilirken, numpy dizisi (ya da liste) tarzı, verinin bulunduğu konuma göre yapılan indekslemede verilen aralığın sonu dilimlemeye dahil edilmez (örn. $dizi[1:4]$ şeklinde bir indekslemede dizinin 1, 2 ve 3 numaralı indekslerinde bulunan değerlerden bir dizi dilimi oluşturulur, 4 numaralı indeksteki değer alınmaz!).
# Veri cercevesinin sadece bir bolumunu secmek icin
gunes_sistemi.loc['jupiter':'merkur', ['Mg', 'Rg']]
Mg | Rg | |
---|---|---|
jupiter | 1898.000 | 71492.0 |
mars | 0.642 | 3396.0 |
merkur | 0.330 | 2439.5 |
gunes_sistemi.loc['ay', ['Prot','Porb']]
Prot 655.7 Porb 27.3 Name: ay, dtype: float64
loc
kullanılarak sütun ya da satır adıyla seçim yapılabileceği gibi indeks numarası kullanılarak verinin bulundğu konum üzerinden de seçim yapılabilir; bunun için iloc
özniteliğine başvurulur.
# seri_tamindeks serisi uzerinde
print(seri_tamindeks.iloc[1])
print(seri_tamindeks.loc[1])
dunya merkur
# seri_tamindeks serisi uzerinde
print(seri_tamindeks.iloc[2])
print(seri_tamindeks.iloc[0:2])
jupiter 1 merkur 3 dunya dtype: object
gunes_sistemi.iloc[4]
Mg 0.33 Rg 2439.50 Prot 1407.60 Porb 88.00 Name: merkur, dtype: float64
gunes_sistemi['Prot'] = gunes_sistemi['Prot'] / 23.90
gunes_sistemi
veriçerçevesindeki nesneleri yörünge dönemine göre sıraladıktan sonra 4. sırada hangi cismin olduğu aşağıdaki örnekte olduğu gibi görülebilir.
gunes_sistemi.sort_values('Porb').iloc[3]
Mg 5.97 Rg 6378.00 Prot 1.00 Porb 365.20 Name: dunya, dtype: float64
gunes_sistemi.sort_values('Porb').iloc[1:5,1]
merkur 2439.5 venus 6052.0 dunya 6378.0 mars 3396.0 Name: Rg, dtype: float64
gunes_sistemi.iloc[[4,3,0],-1]
merkur 88.0 mars 687.0 ay 27.3 Name: Porb, dtype: float64
# Belirli bir deger icin
print(gunes_sistemi.loc['venus','Rg'])
print(gunes_sistemi.iloc[-1, -1])
6052.0 224.7
# Bu islemi daha hizli yapabilen iki metot at ve iat metotlaridir
print(gunes_sistemi.at['dunya','Mg'])
print(gunes_sistemi.iat[1,2]) #1: dunya 2: Porb
5.97 1.0
Tıpkı numpy dizilerinde olduğu gibi pandas veri çerçevelerinde de bir koşula dayanan dilimleemler yapılabilir.
print(gunes_sistemi['Porb'] > 365.25)
ay False dunya False jupiter True mars True merkur False neptun True pluto True saturn True uranus True venus False Name: Porb, dtype: bool
print(gunes_sistemi[gunes_sistemi['Mg'] > 10.00]['Rg'])
jupiter 71492.0 neptun 24764.0 saturn 60268.0 uranus 25559.0 Name: Rg, dtype: float64
Bir koşula göre dilimlemelerde dahi numpy tarzı dilimlemeler ve indekslemelerin dahi pandas tarafından sağlanan loc
, iloc
, at
, iat
özellikleri (attribute) kullanılması önerilmektedir.
print(gunes_sistemi.loc[gunes_sistemi['Prot'] < 24.0])
Mg Rg Prot Porb dunya 5.9700 6378.0 1.000000 365.2 jupiter 1898.0000 71492.0 0.414226 4331.0 mars 0.6420 3396.0 1.029289 687.0 neptun 102.0000 24764.0 0.673640 59800.0 pluto 0.0146 1185.0 -6.414226 90560.0 saturn 568.0000 60268.0 0.447699 10747.0 uranus 86.8000 25559.0 -0.719665 30589.0 venus 4.8700 6052.0 -244.037657 224.7
Herhangi bir değerin bir sütunda olup olmadığını belirlemek için isin
fonksiyonu kullanılır.
gunes_sistemi[gunes_sistemi['Porb'].isin([365.2, 88.00])]
Mg | Rg | Prot | Porb | |
---|---|---|---|---|
dunya | 5.97 | 6378.0 | 1.000000 | 365.2 |
merkur | 0.33 | 2439.5 | 58.895397 | 88.0 |
print(df)
A B C D 2022-02-22 1.357591 1.452445 -0.754914 0.987056 2022-02-23 -1.313615 2.401218 0.705444 2.341917 2022-02-24 0.383417 -1.181176 0.778811 -0.643517 2022-02-25 -1.325880 -0.112487 0.854269 -0.080190 2022-02-26 -1.172382 0.096121 0.241880 0.002872
s1 = [1, 2, 3, 4, 5]
df['E'] = s1
print(df)
A B C D E 2022-02-22 1.357591 1.452445 -0.754914 0.987056 1 2022-02-23 -1.313615 2.401218 0.705444 2.341917 2 2022-02-24 0.383417 -1.181176 0.778811 -0.643517 3 2022-02-25 -1.325880 -0.112487 0.854269 -0.080190 4 2022-02-26 -1.172382 0.096121 0.241880 0.002872 5
Ancak indeksleri vererek yeni bir sütun eklemek daha güvenilir ve tutarlı bir yoldur.
gunes_sistemi['e'] = pd.Series([0.205, 0.007, 0.017, 0.055, 0.094, 0.049, 0.057, 0.046, 0.011, 0.244], \
index = ['merkur','venus', 'dunya', 'ay', 'mars', 'jupiter', 'saturn', 'uranus', 'neptun', 'pluto'])
print(gunes_sistemi)
Mg Rg Prot Porb e ay 0.0730 1737.5 27.435146 27.3 0.055 dunya 5.9700 6378.0 1.000000 365.2 0.017 jupiter 1898.0000 71492.0 0.414226 4331.0 0.049 mars 0.6420 3396.0 1.029289 687.0 0.094 merkur 0.3300 2439.5 58.895397 88.0 0.205 neptun 102.0000 24764.0 0.673640 59800.0 0.011 pluto 0.0146 1185.0 -6.414226 90560.0 0.244 saturn 568.0000 60268.0 0.447699 10747.0 0.057 uranus 86.8000 25559.0 -0.719665 30589.0 0.046 venus 4.8700 6052.0 -244.037657 224.7 0.007
# g/cm^3 cinsinden hacimleri yeni bir sutuna ekleyelim
gunes_sistemi['V'] = gunes_sistemi['Mg']*1e27 / (4./3*np.pi*(gunes_sistemi['Rg']*1e5)**3)
print(gunes_sistemi)
Mg Rg Prot Porb e V ay 0.0730 1737.5 27.435146 27.3 0.055 3.322460 dunya 5.9700 6378.0 1.000000 365.2 0.017 5.493286 jupiter 1898.0000 71492.0 0.414226 4331.0 0.049 1.240039 mars 0.6420 3396.0 1.029289 687.0 0.094 3.913302 merkur 0.3300 2439.5 58.895397 88.0 0.205 5.426538 neptun 102.0000 24764.0 0.673640 59800.0 0.011 1.603427 pluto 0.0146 1185.0 -6.414226 90560.0 0.244 2.094639 saturn 568.0000 60268.0 0.447699 10747.0 0.057 0.619440 uranus 86.8000 25559.0 -0.719665 30589.0 0.046 1.241079 venus 4.8700 6052.0 -244.037657 224.7 0.007 5.244977
Şimdi aslında bir cüce gezegen olmasına karşın Ceres'in parametrelerini yeni bir satır olarak veri çerçevemize ekleyelim ama Ceres'in yörünge dönemini ($P_{orb}$) ve dış merkezliliğini ($e$) girmeyi unutmuş olalım. Ayrıca diğer parameterleri de bir miktar "karışık" bir sırada verelim. Bunun yanı sıra Ceres'in yarıçapını da Dünya yarıçapı cinsinden ($R = 0.074 R_{dunya}$) biliyor olalım. Sona satır ya da sütün ekleme işi pandas 1.4.0
öncesinde append
metoduyla yapılabilirken artık bu metod kullanımdan kaldırılmıştır ve pandas.concat
fonksiyonu bu amaçlarla kullanılmaktadır.
ceres = {'Prot' : pd.Series([9.1], index=['ceres']),\
'Rg' : pd.Series([0.074*gunes_sistemi.at['dunya','Rg']], index=['ceres']),\
'Mg': pd.Series([0.94e-3], index=['ceres'])}
gunes_sistemi = pd.concat([gunes_sistemi,pd.DataFrame(ceres)], axis=0, sort=False)
print(gunes_sistemi)
Mg Rg Prot Porb e V ay 0.07300 1737.500 27.435146 27.3 0.055 3.322460 dunya 5.97000 6378.000 1.000000 365.2 0.017 5.493286 jupiter 1898.00000 71492.000 0.414226 4331.0 0.049 1.240039 mars 0.64200 3396.000 1.029289 687.0 0.094 3.913302 merkur 0.33000 2439.500 58.895397 88.0 0.205 5.426538 neptun 102.00000 24764.000 0.673640 59800.0 0.011 1.603427 pluto 0.01460 1185.000 -6.414226 90560.0 0.244 2.094639 saturn 568.00000 60268.000 0.447699 10747.0 0.057 0.619440 uranus 86.80000 25559.000 -0.719665 30589.0 0.046 1.241079 venus 4.87000 6052.000 -244.037657 224.7 0.007 5.244977 ceres 0.00094 471.972 9.100000 NaN NaN NaN
ganymede = {'Mg' : 148.2e-3, 'Rg' : 2631., 'e' : 0.001}
gunes_sistemi = pd.concat([gunes_sistemi,
pd.DataFrame(ganymede, index=['ganymede'])],
sort=False)
print(gunes_sistemi)
Mg Rg Prot Porb e V ay 0.07300 1737.500 27.435146 27.3 0.055 3.322460 dunya 5.97000 6378.000 1.000000 365.2 0.017 5.493286 jupiter 1898.00000 71492.000 0.414226 4331.0 0.049 1.240039 mars 0.64200 3396.000 1.029289 687.0 0.094 3.913302 merkur 0.33000 2439.500 58.895397 88.0 0.205 5.426538 neptun 102.00000 24764.000 0.673640 59800.0 0.011 1.603427 pluto 0.01460 1185.000 -6.414226 90560.0 0.244 2.094639 saturn 568.00000 60268.000 0.447699 10747.0 0.057 0.619440 uranus 86.80000 25559.000 -0.719665 30589.0 0.046 1.241079 venus 4.87000 6052.000 -244.037657 224.7 0.007 5.244977 ceres 0.00094 471.972 9.100000 NaN NaN NaN ganymede 0.14820 2631.000 NaN NaN 0.001 NaN
İki büyük uydunun (Titan, Triton) parametrelerini daha ekleyelim.
iki_buyuk_uydu = [{'Mg':134.6e-3, 'Rg':2575, 'Prot':382.7, 'e': 0.029}, \
{'Rg':1352.5, 'Prot':-141.0, 'e':0.000, 'Mg':21.5e-3}]
gunes_sistemi = pd.concat([gunes_sistemi,
pd.DataFrame(iki_buyuk_uydu, index=['titan','triton'])],
sort=False)
print(gunes_sistemi)
Mg Rg Prot Porb e V ay 0.07300 1737.500 27.435146 27.3 0.055 3.322460 dunya 5.97000 6378.000 1.000000 365.2 0.017 5.493286 jupiter 1898.00000 71492.000 0.414226 4331.0 0.049 1.240039 mars 0.64200 3396.000 1.029289 687.0 0.094 3.913302 merkur 0.33000 2439.500 58.895397 88.0 0.205 5.426538 neptun 102.00000 24764.000 0.673640 59800.0 0.011 1.603427 pluto 0.01460 1185.000 -6.414226 90560.0 0.244 2.094639 saturn 568.00000 60268.000 0.447699 10747.0 0.057 0.619440 uranus 86.80000 25559.000 -0.719665 30589.0 0.046 1.241079 venus 4.87000 6052.000 -244.037657 224.7 0.007 5.244977 ceres 0.00094 471.972 9.100000 NaN NaN NaN ganymede 0.14820 2631.000 NaN NaN 0.001 NaN titan 0.13460 2575.000 382.700000 NaN 0.029 NaN triton 0.02150 1352.500 -141.000000 NaN 0.000 NaN
Şimdi bakınca Ganymede'in dönme dönemini girmediğimizi farketmiş ve girmek istiyor olalım. Uydular için yörünge dönemi gezegenlerinin etrafındaki yörüngelerinin dönemi olduğu için girmemeyi tercih ettik (Ay hariç).
gunes_sistemi.at['ganymede', 'Prot'] = 171.7
print(gunes_sistemi)
Mg Rg Prot Porb e V ay 0.07300 1737.500 27.435146 27.3 0.055 3.322460 dunya 5.97000 6378.000 1.000000 365.2 0.017 5.493286 jupiter 1898.00000 71492.000 0.414226 4331.0 0.049 1.240039 mars 0.64200 3396.000 1.029289 687.0 0.094 3.913302 merkur 0.33000 2439.500 58.895397 88.0 0.205 5.426538 neptun 102.00000 24764.000 0.673640 59800.0 0.011 1.603427 pluto 0.01460 1185.000 -6.414226 90560.0 0.244 2.094639 saturn 568.00000 60268.000 0.447699 10747.0 0.057 0.619440 uranus 86.80000 25559.000 -0.719665 30589.0 0.046 1.241079 venus 4.87000 6052.000 -244.037657 224.7 0.007 5.244977 ceres 0.00094 471.972 9.100000 NaN NaN NaN ganymede 0.14820 2631.000 171.700000 NaN 0.001 NaN titan 0.13460 2575.000 382.700000 NaN 0.029 NaN triton 0.02150 1352.500 -141.000000 NaN 0.000 NaN
Veri çerçevelerinden sütun silmek için del
komutu (zira bir veri çerçevesi değiştirilemez (ing. immutable) bir nesnedir), satır silmek için ise drop
metodu kullanılır.
print(sehirler)
sehirler['Bolge'] = ['Akdeniz', 'Marmara', 'Ic Anadolu', 'Ege', 'Guneydogu Anadolu', 'Marmara']
print(sehirler)
Plaka Sehir Ozellik 0 01 Adana Kebap 1 34 Istanbul Kalabalik 2 06 Ankara Memurlar 3 35 Izmir Gevrek 4 44 Malatya Kayisi 5 16 Bursa Uludag Plaka Sehir Ozellik Bolge 0 01 Adana Kebap Akdeniz 1 34 Istanbul Kalabalik Marmara 2 06 Ankara Memurlar Ic Anadolu 3 35 Izmir Gevrek Ege 4 44 Malatya Kayisi Guneydogu Anadolu 5 16 Bursa Uludag Marmara
del sehirler['Ozellik']
print(sehirler)
Plaka Sehir Bolge 0 01 Adana Akdeniz 1 34 Istanbul Marmara 2 06 Ankara Ic Anadolu 3 35 Izmir Ege 4 44 Malatya Guneydogu Anadolu 5 16 Bursa Marmara
sehirler.drop(4, axis=0)
Plaka | Sehir | Bolge | |
---|---|---|---|
0 | 01 | Adana | Akdeniz |
1 | 34 | Istanbul | Marmara |
2 | 06 | Ankara | Ic Anadolu |
3 | 35 | Izmir | Ege |
5 | 16 | Bursa | Marmara |
print(sehirler)
Plaka Sehir Bolge 0 01 Adana Akdeniz 1 34 Istanbul Marmara 2 06 Ankara Ic Anadolu 3 35 Izmir Ege 4 44 Malatya Guneydogu Anadolu 5 16 Bursa Marmara
Bu durumu kalıcı hale getirmek için drop
metodunun inplace
anahtarına $True$ değeri atanmalıdır.
sehirler.drop(4, axis=0, inplace=True)
sehirler
Plaka | Sehir | Bolge | |
---|---|---|---|
0 | 01 | Adana | Akdeniz |
1 | 34 | Istanbul | Marmara |
2 | 06 | Ankara | Ic Anadolu |
3 | 35 | Izmir | Ege |
5 | 16 | Bursa | Marmara |
Pandas özünde numpy dizileriyle de birlikte çalışmak üzere tasarlanmış (vektörleştirilmiş) bir veri yönetim paketi olduğu için diziler üzerinde çalışabilen ön tanımlı (built-in) ya da kullanıcı tanımlı fonksiyonlar Pandas veri nesneleri üzerinde çallışır.
import pandas as pd
import numpy as np
rstglvr = np.random.RandomState(42)
rstglsr = pd.Series(rstglvr.randint(0, 20, 5))
rstglsr
0 6 1 19 2 14 3 10 4 7 dtype: int64
rstgldf = pd.DataFrame(rstglvr.randint(0, 20, (4, 5)),
columns=['A', 'B', 'C', 'D', 'E'])
rstgldf
A | B | C | D | E | |
---|---|---|---|---|---|
0 | 6 | 18 | 10 | 10 | 3 |
1 | 7 | 2 | 1 | 11 | 5 |
2 | 1 | 0 | 11 | 11 | 16 |
3 | 9 | 15 | 14 | 14 | 18 |
print(np.sin(rstgldf/16. + np.pi / 2))
A B C D E 0 0.930508 0.431177 0.810963 0.810963 0.982473 1 0.905814 0.992198 0.998048 0.772835 0.951568 2 0.998048 1.000000 0.772835 0.772835 0.540302 3 0.845924 0.591805 0.640997 0.640997 0.431177
Herhangi bir fonksiyon ya da aritmetik işlem birden fazla seri ya da veri çerçevesi arasında uygulanmak istendiğinde Pandas iki veri nesnesinin indekslerini hizalar.
yuzolcum = pd.Series({'Birlesik Krallik': 242495, 'Fransa': 551695, 'Almanya': 357386,
'Ispanya': 498511, 'Turkiye': 783562}, name='yuzolcum')
nufus = pd.Series({'Turkiye': 84200851, 'Ispanya': 46767543, 'Birlesik Krallik': 67803450,
'Almanya': 83792987, 'Fransa': 65227357}, name='yuzolcum')
nufus_yogunlugu = nufus / yuzolcum
print(nufus_yogunlugu)
Almanya 234.460743 Birlesik Krallik 279.607621 Fransa 118.230829 Ispanya 93.814465 Turkiye 107.459079 Name: yuzolcum, dtype: float64
gdp = pd.Series({'Almanya': 3863344, 'Fransa': 2707074, 'Italya': 1988636,
'Izlanda': 24280, 'Turkiye': 743708}, name='yuzolcum')
gdp_kisibasi = gdp / nufus
print(gdp_kisibasi*1e6)
Almanya 46105.815514 Birlesik Krallik NaN Fransa 41502.126171 Ispanya NaN Italya NaN Izlanda NaN Turkiye 8832.547310 Name: yuzolcum, dtype: float64
Bir veri çerçevesi ile bir seri arasında işlem yaparken işlem varsayılan olarak satırda gerçekleşir ve indeksler hizalanır.
A = rstglvr.randint(20, size=(4, 5))
dfA = pd.DataFrame(A, columns=list('XYZTW'))
dfA - dfA.iloc[0]
X | Y | Z | T | W | |
---|---|---|---|---|---|
0 | 0 | 0 | 0 | 0 | 0 |
1 | -5 | -11 | 4 | 13 | -15 |
2 | 2 | -2 | 6 | -3 | 1 |
3 | 3 | -13 | 9 | 3 | -4 |
İşlem sütun üzerinde yapılmak istendiğinde axis
anahtarı işlemin sütun üzerinden yapılacağını belirtmek üzere $0$ 'a eşitlenir
print(dfA)
dfA.subtract(dfA['Z'], axis=0)
X Y Z T W 0 11 19 2 4 18 1 6 8 6 17 3 2 13 17 8 1 19 3 14 6 11 7 14
X | Y | Z | T | W | |
---|---|---|---|---|---|
0 | 9 | 17 | 0 | 2 | 16 |
1 | 0 | 2 | 0 | 11 | -3 |
2 | 5 | 9 | 0 | -7 | 11 |
3 | 3 | -5 | 0 | -4 | 3 |
apply
metodu herhangi bir fonksiyonun tüm veriçerçevesi ya da seri üzerine uygulanmasını sağlar.
import pandas as pd
import numpy as np
rstglvr = np.random.RandomState(42)
print(rstglvr)
A = rstglvr.randn(20)
dfA = pd.DataFrame(A.reshape((4,5)), columns=list('XYZTW'))
print(dfA)
print(dfA.apply(np.cumsum))
RandomState(MT19937) X Y Z T W 0 0.496714 -0.138264 0.647689 1.523030 -0.234153 1 -0.234137 1.579213 0.767435 -0.469474 0.542560 2 -0.463418 -0.465730 0.241962 -1.913280 -1.724918 3 -0.562288 -1.012831 0.314247 -0.908024 -1.412304 X Y Z T W 0 0.496714 -0.138264 0.647689 1.523030 -0.234153 1 0.262577 1.440949 1.415123 1.053555 0.308407 2 -0.200840 0.975219 1.657086 -0.859725 -1.416511 3 -0.763128 -0.037612 1.971333 -1.767749 -2.828815
Bir veri tablosuna ya da pandas diliyle veri çerçevesinde karşılığı bulunmayan bir verinin nasıl girileceği tartışmalı bir konu olup, tek bir çözümü de yoktur. Veri türüne bağlı olarak bazı durumlarda $-1$, $9.9999$, $-99999$ gibi "nöbetçi değer" (ing. sentinel) kullanılabileceği gibi, boş bırakmak, '-', 'NA', 'N/A'gibi belirteçler kullanmak da tercih edilebilmektedir. Bu çözümlerin her birinin avantaj ve dezavantajları bulunur. Örneğin tüm verilerin pozitif olarak girileceği bir sütunda değeri olmayanların yerine $-1$ girmek sütunlar üzerinde matematiksel işlemler yapılırken bu sütunun da dikkate alınması ve CPU'ya bu nedenle ek yük binmesi anlamına gelir.
Pandas, bir veri çerçevesi ya da seride bulunmayacak verilerin yerine $None$ ve $NaN$ nesnelerini kullanır. Ancak $None$ kullanıldığına veri tipi de nesne ($object$) olur ki bu işlemlerin daha kısa sürede yapılmasına olanak sağlayan $NaN$ seçeneğine göre dezavantajlıdır.
for dtype in ['object', 'int']:
print("dtype =", dtype)
%timeit np.arange(1E6, dtype=dtype).sum()
print()
dtype = object 62.5 ms ± 3.4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) dtype = int 1.38 ms ± 42 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)
$NaN$ veri türü IEEE kayan noktalı sayı standartları arasında tanımlanmış ve tüm programlama dilleri ve dijital işlemlerde kullanılan bir veri türüdür. $NaN$ veri türü ile yapılan tüm işlemler sonuç döndürür.
import numpy as np
import pandas as pd
x = np.array([1, np.nan, 3, 4])
print("1 + x = ", 1 + x)
print("0x = ", 0*x)
print("ln(x) = ", np.log(x))
print("min(x) = ", np.min(x))
print("nanmax(x) = ", np.nanmax(x))
print("SIGMA(x) = ", np.sum(x))
print("nansum(x) = ", np.nansum(x))
1 + x = [ 2. nan 4. 5.] 0x = [ 0. nan 0. 0.] ln(x) = [0. nan 1.09861229 1.38629436] min(x) = nan nanmax(x) = 4.0 SIGMA(x) = nan nansum(x) = 8.0
pandas modülünde girilmeyen ya da NaN
(ing. Not a Number) veya None
olarak girilen verileri (Null) yönetmek üzere de özel fonksiyonlar (isnull
, notnull
,dropna
,fillna
) bulunmaktadır.
veri2 = {
'ogrno' : ['08','16','32','74'],
'odev' : [56, 72, 60, 84],
'proje' : [70, 43, 57, 71]
}
ders2 = pd.DataFrame(veri2)
ders2
ogrno | odev | proje | |
---|---|---|---|
0 | 08 | 56 | 70 |
1 | 16 | 72 | 43 |
2 | 32 | 60 | 57 |
3 | 74 | 84 | 71 |
ders2 = pd.concat([ders2,pd.DataFrame({'ogrno' : 18, 'proje' : 37}, index=[4])],
sort=True)
ders2
odev | ogrno | proje | |
---|---|---|---|
0 | 56.0 | 08 | 70 |
1 | 72.0 | 16 | 43 |
2 | 60.0 | 32 | 57 |
3 | 84.0 | 74 | 71 |
4 | NaN | 18 | 37 |
ders2 = pd.concat([ders2,pd.DataFrame({'ogrno' : 24, 'proje' : 65}, index=[5])],
sort=True)
ders2
odev | ogrno | proje | |
---|---|---|---|
0 | 56.0 | 08 | 70 |
1 | 72.0 | 16 | 43 |
2 | 60.0 | 32 | 57 |
3 | 84.0 | 74 | 71 |
4 | NaN | 18 | 37 |
5 | NaN | 24 | 65 |
Nan
olan değerlerin tablodaki yerini isna
fonksiyonuyla görebiliriz.
# isna fonksiyonu Null degeri veren elemanlari True
# digerlerini False isaretleyerek bir maske (mask) olusturur
pd.isna(ders2)
odev | ogrno | proje | |
---|---|---|---|
0 | False | False | False |
1 | False | False | False |
2 | False | False | False |
3 | False | False | False |
4 | True | False | False |
5 | True | False | False |
dropna
$NaN$ değer bulunan satır (varsayılan) ya da sütunları silmek için kullanılır.
ders2.dropna(subset=['odev'])
odev | ogrno | proje | |
---|---|---|---|
0 | 56.0 | 08 | 70 |
1 | 72.0 | 16 | 43 |
2 | 60.0 | 32 | 57 |
3 | 84.0 | 74 | 71 |
Varsayılan davranışında satır silen drop
fonksiyonu NaN
sütunları silmek için de kullanılabilir. $axis = 1$ ya da $axis = columns$ verilerek NaN
barındıran tüm sütunlar silinebilir.
ders2.dropna(axis=1)
ogrno | proje | |
---|---|---|
0 | 08 | 70 |
1 | 16 | 43 |
2 | 32 | 57 |
3 | 74 | 71 |
4 | 18 | 37 |
5 | 24 | 65 |
dropna
fonksiyonunun how
parametresi en az bir değeri ($how = 'any'$) veya tüm değerleri ($how = 'all'$) NaN
olan, satır veya sütunun veri çerçevesinden kaldırılıp kaldırılmayacağını belirler.
ders2.dropna(how='any',axis=1)
ogrno | proje | |
---|---|---|
0 | 08 | 70 |
1 | 16 | 43 |
2 | 32 | 57 |
3 | 74 | 71 |
4 | 18 | 37 |
5 | 24 | 65 |
ders2.dropna(how='all',axis=1)
odev | ogrno | proje | |
---|---|---|---|
0 | 56.0 | 08 | 70 |
1 | 72.0 | 16 | 43 |
2 | 60.0 | 32 | 57 |
3 | 84.0 | 74 | 71 |
4 | NaN | 18 | 37 |
5 | NaN | 24 | 65 |
Bazen $NA$ değerlerini silmek yerine, geçerli bir değerle değiştirmek tercih edilebilir. Bu değer, sıfır gibi tek bir sayı olabilir veya çevredeki değerler kullanılarak yapılabilecek bir interpolasyon sonucu elde edilen değer olabilir. Aslında bu işlem isnull
fonksiyonu ile bir maske (ing. mask) üretilerek $NaN$ değerler belirlendikten sonra istenen değerlerle değiştirilerek de yapılabilir. Ancak bu çok sık kullanılan işlem olduğu için Pandas dizinin bir kopyasını $null$ değerlerle değiştiren fillna
metodunu sağlamıştır.
veri = pd.Series([1, np.nan, 2, None, 3, np.nan], index=list('PQRSTU'))
veri
P 1.0 Q NaN R 2.0 S NaN T 3.0 U NaN dtype: float64
# NaN degerleri 0 ile degistir
veri.fillna(0)
P 1.0 Q 0.0 R 2.0 S 0.0 T 3.0 U 0.0 dtype: float64
# Nan degerleri bir sonraki deger ile degistir
veri.fillna(method='ffill')
P 1.0 Q 1.0 R 2.0 S 2.0 T 3.0 U 3.0 dtype: float64
# Nan degerleri bir onceki deger ile degistir
veri.fillna(method='bfill')
P 1.0 Q 2.0 R 2.0 S 3.0 T 3.0 U NaN dtype: float64
ders2.fillna(0, axis=1)
odev | ogrno | proje | |
---|---|---|---|
0 | 56.0 | 08 | 70 |
1 | 72.0 | 16 | 43 |
2 | 60.0 | 32 | 57 |
3 | 84.0 | 74 | 71 |
4 | 0 | 18 | 37 |
5 | 0 | 24 | 65 |
Pandas modülünden tablo yapısındaki ascii (salt metin), sütunlardaki değerleri virgülle ayrılan (csv), yaygın sayfa programlarıyla oluşturulan pek çok formattaki dosyadan veri çekilip, üzerinde işlemler yapılabilir. Öncelikle sütunlardaki değerleri virgülle ayrılmış bir tablo yapısı (csv) üzerinde bir örnekle çalışalım. ders_notlar.csv dosyasında bir derste öğrencilerin aldığı notlar (iki ödev, bir arasınav ve bir final olmak üzere) verilmiştir. Öncelikle bu dosyadaki veriyi alıp, bir veri çerçevesine aktaralım. Sonrasında buradaki verinin üzerinde işlemler yapabilir ve analiz edebiliriz.
Pandas modülünün csv
fonksiyonu metin değişkenlere aktarılan sütun değerlerinin başında boşluk varsa (whitespace
) bunları da metne dahil ettiğinden bu davranışı değiştirmek üzere skipinitialspace
parametresi True değerine ayarlanmalıdır.
Pandas read_csv
fonksiyonu virgülle ayrılmış olmasalar dahi belirli bir karakterle ayrılmış (delimited) dosyaları veriçerçevelerine dönüştürebilir. Pek çok başka formattaki veri dosyasını da read_excel()
, read_json()
, read_html()
ve read_sql_table()
gibi fonksiyonlar yardımıyla veriçerçevelerine transfer etmek mümkündür. Herhangi bir programdan (excel, emacs, notepad vs.) kopyalanan bir veriyi dahi read_clipboard()
kullanarak veriçerçevesine transfer edebilirsiniz.
import pandas as pd
notlar = pd.read_csv('ders_notlar.csv', index_col="ad", skipinitialspace=True)
notlar
odev1 | odev2 | arasinav | final | durum | |
---|---|---|---|---|---|
ad | |||||
ogrenci1 | 100 | 0 | NaN | NaN | W |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | NaN |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | NaN |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | NaN |
ogrenci5 | 97 | 0 | NaN | NaN | W |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | NaN |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | NaN |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | NaN |
ogrenci9 | 75 | 0 | 68.0 | NaN | W |
ogrenci10 | 95 | 0 | 85.0 | NaN | W |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | NaN |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | NaN |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | NaN |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | NaN |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | NaN |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | NaN |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | NaN |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | NaN |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | NaN |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | NaN |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | NaN |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | NaN |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | NaN |
ogrenci24 | 90 | 0 | NaN | NaN | W |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | NaN |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | NaN |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | NaN |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | NaN |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | NaN |
ogrenci30 | 92 | 0 | 86.0 | NaN | W |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | NaN |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | NaN |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | NaN |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | NaN |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | NaN |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | NaN |
ogrenci37 | 78 | 0 | 47.0 | 23.0 | NaN |
type(notlar)
pandas.core.frame.DataFrame
Eğer ders_notlar.csv dosyasını bir metin editörle açacak olursanız hem NaN
olarak girilen değerler (sınava girmeyenler için), hem de boş bırakılan değerler (durum sütununda henüz durumu belirlenmemiş öğrenciler; W: dersten çekilenleri göstermektedir) göreceksiniz. Pandas boş bırakılan değerleri de NaN
olarak yorumlamaktadır. Tüm sütun isimleri veri dosyasından çekilirken ad sütunu indeks olarak işaretlenmiştir. Başlığı olmayan ya da atlanmak istenen veri dosyaları için csv
fonksiyonunun header
parametresinde çeşitli seçenekler tanımlanmıştır.
# indekslenen sutun
print(notlar.index)
print("-----------------")
# tüm sutunlar
print(notlar.columns)
print("-----------------")
# Herhangi bir ogrencinin butun notlari
print(notlar.loc['ogrenci28'])
print("-----------------")
# Tum arasinav notlari
print(notlar['arasinav'])
Index(['ogrenci1', 'ogrenci2', 'ogrenci3', 'ogrenci4', 'ogrenci5', 'ogrenci6', 'ogrenci7', 'ogrenci8', 'ogrenci9', 'ogrenci10', 'ogrenci11', 'ogrenci12', 'ogrenci13', 'ogrenci14', 'ogrenci15', 'ogrenci16', 'ogrenci17', 'ogrenci18', 'ogrenci19', 'ogrenci20', 'ogrenci21', 'ogrenci22', 'ogrenci23', 'ogrenci24', 'ogrenci25', 'ogrenci26', 'ogrenci27', 'ogrenci28', 'ogrenci29', 'ogrenci30', 'ogrenci31', 'ogrenci32', 'ogrenci33', 'ogrenci34', 'ogrenci35', 'ogrenci36', 'ogrenci37'], dtype='object', name='ad') ----------------- Index(['odev1', 'odev2', 'arasinav', 'final', 'durum'], dtype='object') ----------------- odev1 100 odev2 100 arasinav 81.0 final 76.0 durum NaN Name: ogrenci28, dtype: object ----------------- ad ogrenci1 NaN ogrenci2 64.0 ogrenci3 71.0 ogrenci4 54.0 ogrenci5 NaN ogrenci6 55.0 ogrenci7 91.0 ogrenci8 86.0 ogrenci9 68.0 ogrenci10 85.0 ogrenci11 75.0 ogrenci12 75.0 ogrenci13 72.0 ogrenci14 50.0 ogrenci15 91.0 ogrenci16 75.0 ogrenci17 63.0 ogrenci18 88.0 ogrenci19 59.0 ogrenci20 81.0 ogrenci21 75.0 ogrenci22 85.0 ogrenci23 79.0 ogrenci24 NaN ogrenci25 50.0 ogrenci26 68.0 ogrenci27 63.0 ogrenci28 81.0 ogrenci29 52.0 ogrenci30 86.0 ogrenci31 59.0 ogrenci32 92.0 ogrenci33 92.0 ogrenci34 53.0 ogrenci35 94.0 ogrenci36 76.0 ogrenci37 47.0 Name: arasinav, dtype: float64
notlar.rename(index={"ogrenci37":"mehmet"},inplace=False)
odev1 | odev2 | arasinav | final | durum | |
---|---|---|---|---|---|
ad | |||||
ogrenci1 | 100 | 0 | NaN | NaN | W |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | NaN |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | NaN |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | NaN |
ogrenci5 | 97 | 0 | NaN | NaN | W |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | NaN |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | NaN |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | NaN |
ogrenci9 | 75 | 0 | 68.0 | NaN | W |
ogrenci10 | 95 | 0 | 85.0 | NaN | W |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | NaN |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | NaN |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | NaN |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | NaN |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | NaN |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | NaN |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | NaN |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | NaN |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | NaN |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | NaN |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | NaN |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | NaN |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | NaN |
ogrenci24 | 90 | 0 | NaN | NaN | W |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | NaN |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | NaN |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | NaN |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | NaN |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | NaN |
ogrenci30 | 92 | 0 | 86.0 | NaN | W |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | NaN |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | NaN |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | NaN |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | NaN |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | NaN |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | NaN |
mehmet | 78 | 0 | 47.0 | 23.0 | NaN |
Şimdi bir analiz işlemi yapabiliriz. Örneğin aldığı tüm notlardan öğrencinin ağırlıklı genel ortalamasını çıkarabiliriz. Bu ders için her iki ödevin %10'ar (toplamda %20), arasınavın %30, finalin ise %50 ağırlığının olduğunu varsayalım
notlar['genel_ortalama'] = notlar['odev1']*0.1 + notlar['odev2']*0.1 + notlar['arasinav']*0.3 + notlar['final']*0.5
notlar['genel_ortalama']
ad ogrenci1 NaN ogrenci2 75.4 ogrenci3 84.8 ogrenci4 56.2 ogrenci5 NaN ogrenci6 69.5 ogrenci7 90.8 ogrenci8 84.5 ogrenci9 NaN ogrenci10 NaN ogrenci11 80.5 ogrenci12 87.5 ogrenci13 79.6 ogrenci14 56.5 ogrenci15 96.3 ogrenci16 84.5 ogrenci17 71.9 ogrenci18 94.4 ogrenci19 72.5 ogrenci20 91.3 ogrenci21 83.2 ogrenci22 95.5 ogrenci23 77.7 ogrenci24 NaN ogrenci25 59.5 ogrenci26 77.9 ogrenci27 67.3 ogrenci28 82.3 ogrenci29 69.8 ogrenci30 NaN ogrenci31 77.4 ogrenci32 92.1 ogrenci33 97.6 ogrenci34 69.9 ogrenci35 89.7 ogrenci36 71.8 ogrenci37 33.4 Name: genel_ortalama, dtype: float64
Bu ortalamalar hesaplanırken önemli bir şansımız arasınava girmeyen tüm öğrencilerin finale de girmemiş olması ve finale girmeyen tüm öğrencilerin de dersten çekilmiş (durum: W) olmalarıdır. Durumun bu olması zorunlu değildir. Örneğin bir öğrenci arasınava girmeyip derse devam etmiş, finale girmiş olabilir. Bu durumda arasınav notunu 0 yapmak gerekir. Bu tür ayarlamalar koşul yapılarıyla (if
- elif
- else
) kontrol edilebilir. Ayrıca pandas bu tür kontroller için pratik fonksiyonlar da sağlamaktadır. Örneğin her öğrenci için ağırlıklı ortalama çıkarmak bakımından arasınav ve finale girmeyenlerin notlarını 0 varsaymak iyi bir fikir olacaktır. Öğrencinin dersten çekilip çekilmediği durum sütununda kontrol edilebildiği için (W) bu önemli bir avantaj sağlayacaktır. Bu amaçla veri çerçeveleri üzerine tanımlı fillna
metodu kullanılabilir.
notlar = notlar.fillna(0)
notlar['genel_ortalama'] = notlar['odev1']*0.1 + notlar['odev2']*0.1 + notlar['arasinav']*0.3 + notlar['final']*0.5
notlar
odev1 | odev2 | arasinav | final | durum | genel_ortalama | |
---|---|---|---|---|---|---|
ad | ||||||
ogrenci1 | 100 | 0 | 0.0 | 0.0 | W | 10.0 |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | 0 | 75.4 |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | 0 | 84.8 |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | 0 | 56.2 |
ogrenci5 | 97 | 0 | 0.0 | 0.0 | W | 9.7 |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | 0 | 69.5 |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | 0 | 90.8 |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | 0 | 84.5 |
ogrenci9 | 75 | 0 | 68.0 | 0.0 | W | 27.9 |
ogrenci10 | 95 | 0 | 85.0 | 0.0 | W | 35.0 |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | 0 | 80.5 |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | 0 | 87.5 |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | 0 | 79.6 |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | 0 | 56.5 |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | 0 | 96.3 |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | 0 | 84.5 |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | 0 | 71.9 |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | 0 | 94.4 |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | 0 | 72.5 |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | 0 | 91.3 |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | 0 | 83.2 |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | 0 | 95.5 |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | 0 | 77.7 |
ogrenci24 | 90 | 0 | 0.0 | 0.0 | W | 9.0 |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | 0 | 59.5 |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | 0 | 77.9 |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | 0 | 67.3 |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | 0 | 82.3 |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | 0 | 69.8 |
ogrenci30 | 92 | 0 | 86.0 | 0.0 | W | 35.0 |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | 0 | 77.4 |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | 0 | 92.1 |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | 0 | 97.6 |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | 0 | 69.9 |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | 0 | 89.7 |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | 0 | 71.8 |
ogrenci37 | 78 | 0 | 47.0 | 23.0 | 0 | 33.4 |
Bu durumda durum sütununda da W olmayan satırlar 0 ile doldurulmuştur. Ayrıca arasınav ya da finale girmeyen öğrencilerin genel ortalaması NaN
olarak belirlenmiş olduğu için onlar da 0'a dönüştürülmüştür. Bu nedenle genel_ortalama sütununu tekrar hesaplamakta yarar görülmüştür. Şimdi, durum sütunu ortalama notlarına bağlı olarak verilecek olan harf notları ile güncellenebilir.
ogrenciler = notlar.index.values
print(ogrenciler)
for i, ortalama in enumerate(notlar['genel_ortalama']):
if ortalama > 89.500:
notlar.at[ogrenciler[i], 'durum'] = 'A'
notlar
['ogrenci1' 'ogrenci2' 'ogrenci3' 'ogrenci4' 'ogrenci5' 'ogrenci6' 'ogrenci7' 'ogrenci8' 'ogrenci9' 'ogrenci10' 'ogrenci11' 'ogrenci12' 'ogrenci13' 'ogrenci14' 'ogrenci15' 'ogrenci16' 'ogrenci17' 'ogrenci18' 'ogrenci19' 'ogrenci20' 'ogrenci21' 'ogrenci22' 'ogrenci23' 'ogrenci24' 'ogrenci25' 'ogrenci26' 'ogrenci27' 'ogrenci28' 'ogrenci29' 'ogrenci30' 'ogrenci31' 'ogrenci32' 'ogrenci33' 'ogrenci34' 'ogrenci35' 'ogrenci36' 'ogrenci37']
odev1 | odev2 | arasinav | final | durum | genel_ortalama | |
---|---|---|---|---|---|---|
ad | ||||||
ogrenci1 | 100 | 0 | 0.0 | 0.0 | W | 10.0 |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | 0 | 75.4 |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | 0 | 84.8 |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | 0 | 56.2 |
ogrenci5 | 97 | 0 | 0.0 | 0.0 | W | 9.7 |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | 0 | 69.5 |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | A | 90.8 |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | 0 | 84.5 |
ogrenci9 | 75 | 0 | 68.0 | 0.0 | W | 27.9 |
ogrenci10 | 95 | 0 | 85.0 | 0.0 | W | 35.0 |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | 0 | 80.5 |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | 0 | 87.5 |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | 0 | 79.6 |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | 0 | 56.5 |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | A | 96.3 |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | 0 | 84.5 |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | 0 | 71.9 |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | A | 94.4 |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | 0 | 72.5 |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | A | 91.3 |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | 0 | 83.2 |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | A | 95.5 |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | 0 | 77.7 |
ogrenci24 | 90 | 0 | 0.0 | 0.0 | W | 9.0 |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | 0 | 59.5 |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | 0 | 77.9 |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | 0 | 67.3 |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | 0 | 82.3 |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | 0 | 69.8 |
ogrenci30 | 92 | 0 | 86.0 | 0.0 | W | 35.0 |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | 0 | 77.4 |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | A | 92.1 |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | A | 97.6 |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | 0 | 69.9 |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | A | 89.7 |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | 0 | 71.8 |
ogrenci37 | 78 | 0 | 47.0 | 23.0 | 0 | 33.4 |
Aynı sonucu dilimleme için koşul kullanmak suretiyle de almak mümkündür. Veri çerçeveleri üzerinde tanımlı loc
metodu herhangi bir veya birden fazla sütunda istenen koşulu sağlayan satırları seçmek için kullanılablir. Bu satırlar seçildikten sonra bu koşulların sağlandığı satırda yer alan istenen sütun(lar) yeni değerleri ile güncellenebilir. Bu noktada birden fazla koşulun and
ya da or
gibi bir bağlaçla bağlanarak kombine koşullar oluşturulması mümkün olmakla birlikte pandas'ın and
ve or
yerine bitwise boolean operatörlerini ( &
ve |
) kullanıyor olmasına dikkat etmek gerekir.
notlar.loc[(notlar['genel_ortalama'] >= 87.500) & (notlar['genel_ortalama'] < 89.500), ['durum']] = 'A-'
notlar.loc[(notlar['genel_ortalama'] >= 84.000) & (notlar['genel_ortalama'] < 87.500), ['durum']] = 'B+'
notlar.loc[(notlar['genel_ortalama'] >= 79.500) & (notlar['genel_ortalama'] < 84.500), ['durum']] = 'B'
notlar.loc[(notlar['genel_ortalama'] >= 76.500) & (notlar['genel_ortalama'] < 79.500), ['durum']] = 'B-'
notlar.loc[(notlar['genel_ortalama'] >= 72.500) & (notlar['genel_ortalama'] < 76.500), ['durum']] = 'C+'
notlar.loc[(notlar['genel_ortalama'] >= 69.500) & (notlar['genel_ortalama'] < 72.500), ['durum']] = 'C'
notlar.loc[(notlar['genel_ortalama'] >= 64.500) & (notlar['genel_ortalama'] < 69.500), ['durum']] = 'C-'
notlar.loc[(notlar['genel_ortalama'] >= 59.500) & (notlar['genel_ortalama'] < 64.500), ['durum']] = 'D+'
notlar.loc[(notlar['genel_ortalama'] >= 54.500) & (notlar['genel_ortalama'] < 59.500), ['durum']] = 'D'
notlar.loc[(notlar['genel_ortalama'] < 54.500) & (notlar['durum'] != 'W'), ['durum']] = 'F'
notlar
odev1 | odev2 | arasinav | final | durum | genel_ortalama | |
---|---|---|---|---|---|---|
ad | ||||||
ogrenci1 | 100 | 0 | 0.0 | 0.0 | W | 10.0 |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | C+ | 75.4 |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | B+ | 84.8 |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | D | 56.2 |
ogrenci5 | 97 | 0 | 0.0 | 0.0 | W | 9.7 |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | C | 69.5 |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | A | 90.8 |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | B+ | 84.5 |
ogrenci9 | 75 | 0 | 68.0 | 0.0 | W | 27.9 |
ogrenci10 | 95 | 0 | 85.0 | 0.0 | W | 35.0 |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | B | 80.5 |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | A- | 87.5 |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | B | 79.6 |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | D | 56.5 |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | A | 96.3 |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | B+ | 84.5 |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | C | 71.9 |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | A | 94.4 |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | C+ | 72.5 |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | A | 91.3 |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | B | 83.2 |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | A | 95.5 |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | B- | 77.7 |
ogrenci24 | 90 | 0 | 0.0 | 0.0 | W | 9.0 |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | D+ | 59.5 |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | B- | 77.9 |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | C- | 67.3 |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | B | 82.3 |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | C | 69.8 |
ogrenci30 | 92 | 0 | 86.0 | 0.0 | W | 35.0 |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | B- | 77.4 |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | A | 92.1 |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | A | 97.6 |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | C | 69.9 |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | A | 89.7 |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | C | 71.8 |
ogrenci37 | 78 | 0 | 47.0 | 23.0 | F | 33.4 |
pandas'ın istatistiki analize yönelik pek çok fonksiyonu bulunmaktadır. Bunlardan bazılarını örnekleyelim.
notlar.describe()
odev1 | odev2 | arasinav | final | genel_ortalama | |
---|---|---|---|---|---|
count | 37.000000 | 37.000000 | 37.000000 | 37.000000 | 37.000000 |
mean | 91.567568 | 77.189189 | 66.351351 | 64.162162 | 68.862162 |
std | 17.234559 | 41.321126 | 24.261556 | 32.707044 | 25.339926 |
min | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 9.000000 |
25% | 90.000000 | 92.000000 | 55.000000 | 59.000000 | 59.500000 |
50% | 95.000000 | 100.000000 | 72.000000 | 76.000000 | 77.400000 |
75% | 100.000000 | 100.000000 | 85.000000 | 86.000000 | 84.800000 |
max | 100.000000 | 100.000000 | 94.000000 | 100.000000 | 97.600000 |
notlar['durum'].describe()
count 37 unique 12 top A freq 8 Name: durum, dtype: object
notlar.sort_values(by=["final","genel_ortalama"])
odev1 | odev2 | arasinav | final | durum | genel_ortalama | |
---|---|---|---|---|---|---|
ad | ||||||
ogrenci24 | 90 | 0 | 0.0 | 0.0 | W | 9.0 |
ogrenci5 | 97 | 0 | 0.0 | 0.0 | W | 9.7 |
ogrenci1 | 100 | 0 | 0.0 | 0.0 | W | 10.0 |
ogrenci9 | 75 | 0 | 68.0 | 0.0 | W | 27.9 |
ogrenci10 | 95 | 0 | 85.0 | 0.0 | W | 35.0 |
ogrenci30 | 92 | 0 | 86.0 | 0.0 | W | 35.0 |
ogrenci37 | 78 | 0 | 47.0 | 23.0 | F | 33.4 |
ogrenci4 | 100 | 100 | 54.0 | 40.0 | D | 56.2 |
ogrenci14 | 95 | 100 | 50.0 | 44.0 | D | 56.5 |
ogrenci27 | 92 | 97 | 63.0 | 59.0 | C- | 67.3 |
ogrenci6 | 100 | 100 | 55.0 | 66.0 | C | 69.5 |
ogrenci17 | 95 | 100 | 63.0 | 67.0 | C | 71.9 |
ogrenci29 | 100 | 97 | 52.0 | 69.0 | C | 69.8 |
ogrenci34 | 95 | 100 | 53.0 | 69.0 | C | 69.9 |
ogrenci23 | 90 | 100 | 79.0 | 70.0 | B- | 77.7 |
ogrenci25 | 0 | 75 | 50.0 | 74.0 | D+ | 59.5 |
ogrenci26 | 100 | 100 | 68.0 | 75.0 | B- | 77.9 |
ogrenci19 | 70 | 98 | 59.0 | 76.0 | C+ | 72.5 |
ogrenci11 | 100 | 100 | 75.0 | 76.0 | B | 80.5 |
ogrenci28 | 100 | 100 | 81.0 | 76.0 | B | 82.3 |
ogrenci13 | 95 | 100 | 72.0 | 77.0 | B | 79.6 |
ogrenci2 | 80 | 92 | 64.0 | 78.0 | C+ | 75.4 |
ogrenci8 | 97 | 100 | 86.0 | 78.0 | B+ | 84.5 |
ogrenci36 | 95 | 0 | 76.0 | 79.0 | C | 71.8 |
ogrenci31 | 87 | 100 | 59.0 | 82.0 | B- | 77.4 |
ogrenci21 | 95 | 97 | 75.0 | 83.0 | B | 83.2 |
ogrenci35 | 100 | 100 | 94.0 | 83.0 | A | 89.7 |
ogrenci16 | 90 | 100 | 75.0 | 86.0 | B+ | 84.5 |
ogrenci7 | 100 | 100 | 91.0 | 87.0 | A | 90.8 |
ogrenci3 | 95 | 100 | 71.0 | 88.0 | B+ | 84.8 |
ogrenci32 | 100 | 100 | 92.0 | 89.0 | A | 92.1 |
ogrenci12 | 90 | 100 | 75.0 | 92.0 | A- | 87.5 |
ogrenci20 | 100 | 100 | 81.0 | 94.0 | A | 91.3 |
ogrenci18 | 100 | 100 | 88.0 | 96.0 | A | 94.4 |
ogrenci15 | 100 | 100 | 91.0 | 98.0 | A | 96.3 |
ogrenci22 | 100 | 100 | 85.0 | 100.0 | A | 95.5 |
ogrenci33 | 100 | 100 | 92.0 | 100.0 | A | 97.6 |
pandas
'ın yeni versiyonlarında istatistiksel işlemler yapılmak istenen sütunlarının bu işleme uygun yapıda olup olmadığı da değerlendirildiğinden, sadece yapılmak istenen uygun sütunların seçilerek ilgili fonksiyon ya da metodun üzerine uygulanması gerekmektedir. Bu nedenle aşağıda ortalaması mean
metoduyla alınmak istenen sütunlar önce select_dtypes(include=np.number)
metoduyla belirlenmiş, sonra mean()
metodu uygulanmıştır.
import numpy as np
notlar.select_dtypes(include=np.number).mean()
odev1 91.567568 odev2 77.189189 arasinav 66.351351 final 64.162162 genel_ortalama 68.862162 dtype: float64
notlar[['odev1','odev2','arasinav','final','genel_ortalama']].median()
odev1 95.0 odev2 100.0 arasinav 72.0 final 76.0 genel_ortalama 77.4 dtype: float64
notlar.select_dtypes(include=np.number).max()
odev1 100.0 odev2 100.0 arasinav 94.0 final 100.0 genel_ortalama 97.6 dtype: float64
Biraz da analiz yapmak üzere derste alınan notları inceleyelim.
notlar["durum"].value_counts()
A 8 W 6 C 5 B 4 B+ 3 B- 3 C+ 2 D 2 A- 1 D+ 1 C- 1 F 1 Name: durum, dtype: int64
Her ne kadar örnekteki veri dosyasyının büyük olmadığından ondan oluşturulan veriçerçevesi üzerindeki işlemler çok hızlı gerçekleşse de string nesneleri işlemleri oldukça yavaşlatır. pandas
string nesneleri gibi nümerik olmayan, heterojen yapıdaki serileri object
nesnesi olarak saklar. Bu veriler hem çok yer kaplar, hem de işlemleri yavaşlatır. Sadece belirli string değerlerini alan object
türündeki veri category
türüne dönüştürülerek hem yerden, hem işlem hızından kazanılabilir.
notlar = notlar.astype({"durum":'category'})
notlar['durum'].dtype
CategoricalDtype(categories=['A', 'A-', 'B', 'B+', 'B-', 'C', 'C+', 'C-', 'D', 'D+', 'F', 'W'], , ordered=False)
Bu veriçerçevesi kategorik veri taşıdığı için doğrudan hist
fonksiyonunu kullanamasak da bir histogram görmek için plot
fonksiyonunun bar
seçeneğini kullanabiliriz.
from matplotlib import pyplot as plt
notlar['durum'].value_counts().plot(kind='bar')
plt.show()
Veri çerçevesi nesnelerinin üzerinde çizim fonksiyounu (plot
) da tanımlıdır. Bunun için ayrıca matplotlib kütüphanesi çağırmaya gerek yoktur, çünkü çizim fonksiyonu matplotlib'i kendi çağırır.
%matplotlib inline
notlar['final'].plot(marker="o",ls="None")
plt.axhline(y = notlar['final'].mean(), ls="--",color="red")
plt.axhline(y = notlar['final'].median(), ls="--",color="green")
plt.show()
%matplotlib inline
notlar['final'].plot(marker="o",ls="None")
plt.axhline(y = notlar[notlar['final'] != 0.]['final'].mean(), ls="--",color="red")
plt.axhline(y = notlar[notlar['final'] != 0.]['final'].median(), ls="--",color="green")
plt.show()
notlar.plot.scatter(x="arasinav", y="final", marker="o")
plt.show()
pandas veri çerçeveleri kolaylıkla $\LaTeX$ formatındaki tablolara dönüştürülüp, yayınlara aktarılabilir.
notlar_latex = notlar.style.to_latex()
print(notlar_latex)
\begin{tabular}{lrrrrlr} & odev1 & odev2 & arasinav & final & durum & genel_ortalama \\ ad & & & & & & \\ ogrenci1 & 100 & 0 & 0.000000 & 0.000000 & W & 10.000000 \\ ogrenci2 & 80 & 92 & 64.000000 & 78.000000 & C+ & 75.400000 \\ ogrenci3 & 95 & 100 & 71.000000 & 88.000000 & B+ & 84.800000 \\ ogrenci4 & 100 & 100 & 54.000000 & 40.000000 & D & 56.200000 \\ ogrenci5 & 97 & 0 & 0.000000 & 0.000000 & W & 9.700000 \\ ogrenci6 & 100 & 100 & 55.000000 & 66.000000 & C & 69.500000 \\ ogrenci7 & 100 & 100 & 91.000000 & 87.000000 & A & 90.800000 \\ ogrenci8 & 97 & 100 & 86.000000 & 78.000000 & B+ & 84.500000 \\ ogrenci9 & 75 & 0 & 68.000000 & 0.000000 & W & 27.900000 \\ ogrenci10 & 95 & 0 & 85.000000 & 0.000000 & W & 35.000000 \\ ogrenci11 & 100 & 100 & 75.000000 & 76.000000 & B & 80.500000 \\ ogrenci12 & 90 & 100 & 75.000000 & 92.000000 & A- & 87.500000 \\ ogrenci13 & 95 & 100 & 72.000000 & 77.000000 & B & 79.600000 \\ ogrenci14 & 95 & 100 & 50.000000 & 44.000000 & D & 56.500000 \\ ogrenci15 & 100 & 100 & 91.000000 & 98.000000 & A & 96.300000 \\ ogrenci16 & 90 & 100 & 75.000000 & 86.000000 & B+ & 84.500000 \\ ogrenci17 & 95 & 100 & 63.000000 & 67.000000 & C & 71.900000 \\ ogrenci18 & 100 & 100 & 88.000000 & 96.000000 & A & 94.400000 \\ ogrenci19 & 70 & 98 & 59.000000 & 76.000000 & C+ & 72.500000 \\ ogrenci20 & 100 & 100 & 81.000000 & 94.000000 & A & 91.300000 \\ ogrenci21 & 95 & 97 & 75.000000 & 83.000000 & B & 83.200000 \\ ogrenci22 & 100 & 100 & 85.000000 & 100.000000 & A & 95.500000 \\ ogrenci23 & 90 & 100 & 79.000000 & 70.000000 & B- & 77.700000 \\ ogrenci24 & 90 & 0 & 0.000000 & 0.000000 & W & 9.000000 \\ ogrenci25 & 0 & 75 & 50.000000 & 74.000000 & D+ & 59.500000 \\ ogrenci26 & 100 & 100 & 68.000000 & 75.000000 & B- & 77.900000 \\ ogrenci27 & 92 & 97 & 63.000000 & 59.000000 & C- & 67.300000 \\ ogrenci28 & 100 & 100 & 81.000000 & 76.000000 & B & 82.300000 \\ ogrenci29 & 100 & 97 & 52.000000 & 69.000000 & C & 69.800000 \\ ogrenci30 & 92 & 0 & 86.000000 & 0.000000 & W & 35.000000 \\ ogrenci31 & 87 & 100 & 59.000000 & 82.000000 & B- & 77.400000 \\ ogrenci32 & 100 & 100 & 92.000000 & 89.000000 & A & 92.100000 \\ ogrenci33 & 100 & 100 & 92.000000 & 100.000000 & A & 97.600000 \\ ogrenci34 & 95 & 100 & 53.000000 & 69.000000 & C & 69.900000 \\ ogrenci35 & 100 & 100 & 94.000000 & 83.000000 & A & 89.700000 \\ ogrenci36 & 95 & 0 & 76.000000 & 79.000000 & C & 71.800000 \\ ogrenci37 & 78 & 0 & 47.000000 & 23.000000 & F & 33.400000 \\ \end{tabular}
Sonuç olarak oluşan notlar veriçerçevesini yine virgülle ayrılmış bir salt metin dosyasına (ders_notlar_sonuc.csv) adıyla yazdıralım. df.to_json
gibi fonksiyonlarla dosyalara başka türden formatlarda da yazmak mümkündür.
#notlar.options.display.float_format = '{:.2f}'.format
notlar['genel_ortalama'] = notlar['genel_ortalama'].map('{:.2f}'.format)
notlar.to_csv("ders_notlar_sonuc.csv")