800100715151 Astronomide Veritabanları¶

Ders - 02 Pandas Paketi'ne Giriş¶

Doç. Dr. Özgür Baştürk
Ankara Üniversitesi, Astronomi ve Uzay Bilimleri Bölümü
obasturk at ankara.edu.tr
http://ozgur.astrotux.org

Pandas Paketine Giriş¶

  • Pandas Modülü
  • series Nesnesi
    • series Nesnesi Üzerinde İşlemler
    • pandas Serilerine Yeni Veriler Ekleme
  • Veri Çerçeveleri DataFrames
    • Bir Veri Çerçevesi Oluşturmak
    • Veri Çerçevelerinin Görüntülenmesi
    • Veri Çerçevelerinin Dilimlenmesi ve İndekslenmesi
      • Kullanıcı Tanımlı İndeksler ve Konuma Bağlı İndeksler
      • Kullanıcı Tanımlı İndekslerle Seçim ve Dilimleme
    • Veri Çerçevelerinde Değişiklik Yapmak
    • Veri Çerçevelerine Sütun Eklemek
    • Veri Çerçevelerine Satır Eklemek
    • Veri Çerçevelerinden Satır ya da Sütun Silmek
  • Pandas Veri Nesneleri Üzerinde Fonksiyon Kullanımı
  • Girilmeyen Verilerin Yönetimi
    • NaN Veri Türü
    • dropna Fonksiyonu
    • fillna Fonksiyonu
  • Dosyalardan Veri Almak
  • Kaynaklar

pandas Modülü¶

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.

series Nesnesi¶

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.

In [1]:
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.

In [2]:
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
In [3]:
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'>
In [4]:
pd.Series(yldz_mV, index=['Vega', 'Sirius', 'Altair', 'Proxima'])
Out[4]:
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.

In [5]:
print(yldz_mV.name)
None
In [6]:
yldz_mV.name = "yildizlar"
print(yldz_mV)
Sirius     -0.5
Vega        0.0
Proxima    13.6
Name: yildizlar, dtype: float64

Başa Dön

series Nesnesi Üzerinde İşlemler¶

Tıpkı bir numpy dizisi gibi pandas series nesnesi üzerinde işlemler yapılabilir ve fonksiyonlar uygulanabilir, indeksleme ve dilimleme özellikleri kullanılabilir.

In [7]:
print(gzgn_kutleler[::2])
merkur        0.33
dunya         5.97
jupiter    1898.00
uranus       86.80
Name: gezegenler, dtype: float64
In [8]:
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
In [9]:
print(gzgn_kutleler[gzgn_kutleler < gzgn_kutleler['uranus']])
merkur    0.330
venus     4.870
dunya     5.970
mars      0.642
Name: gezegenler, dtype: float64
In [10]:
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
In [11]:
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.
In [12]:
'Betelgeuse' in yldz_mV
Out[12]:
False
In [13]:
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
In [14]:
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.

In [15]:
a = s2[1:]
print(a)
1    4.025176
2   -2.235994
3   -2.221468
4   -1.036793
dtype: float64
In [16]:
s2[1:] + s2[:-2]
Out[16]:
0         NaN
1    8.050352
2   -4.471989
3         NaN
4         NaN
dtype: float64
In [17]:
print(yldz_mV.name)
yldz_mV = yldz_mV.rename('mV')
print(yldz_mV.name)
yildizlar
mV

Başa Dön

pandas Serilerine Yeni Veriler Ekleme¶

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.

In [18]:
pd.__version__
Out[18]:
'1.4.3'
In [19]:
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
In [20]:
print("Saturn'un kutlesi, {:.4f} Jupiter kutlesidir.".format(gzgn_kutleler['saturn'] / gzgn_kutleler['jupiter']))
Saturn'un kutlesi, 0.2993 Jupiter kutlesidir.

Başa Dön

Veri Çerçeveleri DataFrames¶

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 Veri Çerçevesi Oluşturmak¶

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

  • 1 boyutlu listeler (list), sözlükler (dictionary), seriler (series),
  • 2 boyutlu numpy dizileri,
  • Yapılandırılmış ndarray nesneleri,
  • ve diğer veri çerçeveleri kullanılarak tanımlanabilir ya da başlatılabilir.

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.

In [21]:
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)
In [22]:
gunes_sistemi
Out[22]:
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.

In [23]:
# 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
In [24]:
# 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
In [25]:
# 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
In [26]:
# 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

Başa Dön

Veri Çerçevelerinin Görüntülenmesi¶

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.

In [27]:
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
----------------------
In [28]:
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
In [29]:
print(gunes_sistemi.columns)
Index(['Mg', 'Rg', 'Prot', 'Porb'], dtype='object')
In [30]:
cols = [col for col in gunes_sistemi.columns]
gunes_sistemi[cols].dtypes
Out[30]:
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.

In [31]:
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.

In [32]:
gunes_sistemi.sort_values(by='Rg')
Out[32]:
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

Başa Dön

Veri Çerçevelerinin Dilimlenmesi ve İndekslenmesi¶

İ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:

  • Sütın seçme: df[col] (ilgili sütundaki seriyi getirir)
  • Satır seçme: df.loc[label] (ilgii satırdaki seriyi getirir)
  • Satırı indeks değeri ile seçme: df.iloc[loc] (ilgii satırdaki seriyi getirir)
  • Satırda dilimleme: df[5:10] (Veri çerçevesinin dilimlenmiş bölümünü getirir)
  • Satırı bir koşulla seçme: 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.

In [33]:
gunes_sistemi[::2]
Out[33]:
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
In [34]:
gunes_sistemi[-1:0:-2]
Out[34]:
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

Başa Dön

Kullanıcı Tanımlı İndeksler ve Konuma Bağlı İndeksler¶

İ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.

In [35]:
gunes_sistemi['jupiter':'pluto']
Out[35]:
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.

In [36]:
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.

In [37]:
# seri_tamindeks uzerinde bu kez kullanici indeksiyle veri secelim
print(seri_tamindeks.loc[5])
jupiter
In [38]:
# Gunes Sistemi veri cercevesi uzerinde
# Herhangi satir(lar)i indeksiyle secmek icin
gunes_sistemi.loc['jupiter']
Out[38]:
Mg       1898.0
Rg      71492.0
Prot        9.9
Porb     4331.0
Name: jupiter, dtype: float64

Başa Dön

Kullanıcı Tanımlı İndekslerle Seçim ve Dilimleme¶

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!).

In [39]:
# Veri cercevesinin sadece bir bolumunu secmek icin
gunes_sistemi.loc['jupiter':'merkur', ['Mg', 'Rg']]
Out[39]:
Mg Rg
jupiter 1898.000 71492.0
mars 0.642 3396.0
merkur 0.330 2439.5
In [40]:
gunes_sistemi.loc['ay', ['Prot','Porb']]
Out[40]:
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.

In [41]:
# seri_tamindeks serisi uzerinde
print(seri_tamindeks.iloc[1])
print(seri_tamindeks.loc[1])
dunya
merkur
In [42]:
# seri_tamindeks serisi uzerinde
print(seri_tamindeks.iloc[2])
print(seri_tamindeks.iloc[0:2])
jupiter
1    merkur
3     dunya
dtype: object
In [43]:
gunes_sistemi.iloc[4]
Out[43]:
Mg         0.33
Rg      2439.50
Prot    1407.60
Porb      88.00
Name: merkur, dtype: float64
In [44]:
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.

In [45]:
gunes_sistemi.sort_values('Porb').iloc[3]
Out[45]:
Mg         5.97
Rg      6378.00
Prot       1.00
Porb     365.20
Name: dunya, dtype: float64
In [46]:
gunes_sistemi.sort_values('Porb').iloc[1:5,1]
Out[46]:
merkur    2439.5
venus     6052.0
dunya     6378.0
mars      3396.0
Name: Rg, dtype: float64
In [47]:
gunes_sistemi.iloc[[4,3,0],-1]
Out[47]:
merkur     88.0
mars      687.0
ay         27.3
Name: Porb, dtype: float64
In [48]:
# Belirli bir deger icin
print(gunes_sistemi.loc['venus','Rg'])
print(gunes_sistemi.iloc[-1, -1])
6052.0
224.7
In [49]:
# 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.

In [50]:
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
In [51]:
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.

In [52]:
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.

In [53]:
gunes_sistemi[gunes_sistemi['Porb'].isin([365.2, 88.00])]
Out[53]:
Mg Rg Prot Porb
dunya 5.97 6378.0 1.000000 365.2
merkur 0.33 2439.5 58.895397 88.0

Başa Dön

Veri Çerçevelerinde Değişiklik Yapmak¶

Veri Çerçevelerine Sütun Eklemek¶

Veri çerçevesine bir sütun eklenmek istenirken indeksler (satırların isimleri ya da indeks numaraları) verilmezse satırların sırası takip edilir.

In [54]:
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
In [55]:
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.

In [56]:
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
In [57]:
# 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

Başa Dön

Veri Çerçevelerine Satır Eklemek¶

Ş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.

In [58]:
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
In [59]:
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.

In [60]:
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ç).

In [61]:
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

Başa Dön

Veri Çerçevelerinden Satır ya da Sütun Silmek¶

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.

In [62]:
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
In [63]:
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
In [64]:
sehirler.drop(4, axis=0)
Out[64]:
Plaka Sehir Bolge
0 01 Adana Akdeniz
1 34 Istanbul Marmara
2 06 Ankara Ic Anadolu
3 35 Izmir Ege
5 16 Bursa Marmara
In [65]:
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.

In [66]:
sehirler.drop(4, axis=0, inplace=True)
sehirler
Out[66]:
Plaka Sehir Bolge
0 01 Adana Akdeniz
1 34 Istanbul Marmara
2 06 Ankara Ic Anadolu
3 35 Izmir Ege
5 16 Bursa Marmara

Başa Dön

Pandas Veri Nesneleri Üzerinde Fonksiyon Kullanımı¶

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.

In [67]:
import pandas as pd
import numpy as np
rstglvr = np.random.RandomState(42)
rstglsr = pd.Series(rstglvr.randint(0, 20, 5))
rstglsr
Out[67]:
0     6
1    19
2    14
3    10
4     7
dtype: int64
In [68]:
rstgldf = pd.DataFrame(rstglvr.randint(0, 20, (4, 5)),
columns=['A', 'B', 'C', 'D', 'E'])
rstgldf
Out[68]:
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
In [69]:
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.

In [70]:
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
In [71]:
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.

In [72]:
A = rstglvr.randint(20, size=(4, 5))
dfA = pd.DataFrame(A, columns=list('XYZTW'))
dfA - dfA.iloc[0]
Out[72]:
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

In [73]:
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
Out[73]:
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¶

apply metodu herhangi bir fonksiyonun tüm veriçerçevesi ya da seri üzerine uygulanmasını sağlar.

In [74]:
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

Başa Dön

Girilmeyen Verilerin Yönetimi¶

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.

In [75]:
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)

Başa Dön

NaN Veri Türü¶

$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.

In [76]:
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.

In [77]:
veri2 = {
    'ogrno' : ['08','16','32','74'],
    'odev' : [56, 72, 60, 84], 
    'proje' : [70, 43, 57, 71]
}
ders2 = pd.DataFrame(veri2)
ders2
Out[77]:
ogrno odev proje
0 08 56 70
1 16 72 43
2 32 60 57
3 74 84 71
In [78]:
ders2 = pd.concat([ders2,pd.DataFrame({'ogrno' : 18, 'proje' : 37}, index=[4])], 
                  sort=True)
ders2
Out[78]:
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
In [79]:
ders2 = pd.concat([ders2,pd.DataFrame({'ogrno' : 24, 'proje' : 65}, index=[5])], 
                  sort=True)
ders2
Out[79]:
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.

In [80]:
# isna fonksiyonu Null degeri veren elemanlari True
# digerlerini False isaretleyerek bir maske (mask) olusturur 
pd.isna(ders2)
Out[80]:
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

Başa Dön

dropna Fonksiyonu¶

dropna $NaN$ değer bulunan satır (varsayılan) ya da sütunları silmek için kullanılır.

In [81]:
ders2.dropna(subset=['odev'])
Out[81]:
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.

In [82]:
ders2.dropna(axis=1)
Out[82]:
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.

In [83]:
ders2.dropna(how='any',axis=1)
Out[83]:
ogrno proje
0 08 70
1 16 43
2 32 57
3 74 71
4 18 37
5 24 65
In [84]:
ders2.dropna(how='all',axis=1)
Out[84]:
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

Başa Dön

fillna Fonksiyonu¶

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.

In [85]:
veri = pd.Series([1, np.nan, 2, None, 3, np.nan], index=list('PQRSTU'))
veri
Out[85]:
P    1.0
Q    NaN
R    2.0
S    NaN
T    3.0
U    NaN
dtype: float64
In [86]:
# NaN degerleri 0 ile degistir
veri.fillna(0)
Out[86]:
P    1.0
Q    0.0
R    2.0
S    0.0
T    3.0
U    0.0
dtype: float64
In [87]:
# Nan degerleri bir sonraki deger ile degistir
veri.fillna(method='ffill')
Out[87]:
P    1.0
Q    1.0
R    2.0
S    2.0
T    3.0
U    3.0
dtype: float64
In [88]:
# Nan degerleri bir onceki deger ile degistir
veri.fillna(method='bfill')
Out[88]:
P    1.0
Q    2.0
R    2.0
S    3.0
T    3.0
U    NaN
dtype: float64
In [89]:
ders2.fillna(0, axis=1)
Out[89]:
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

Başa Dön

Dosyalardan Veri Almak¶

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.

In [90]:
import pandas as pd
notlar = pd.read_csv('ders_notlar.csv', index_col="ad", skipinitialspace=True)
notlar
Out[90]:
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
In [91]:
type(notlar)
Out[91]:
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.

In [92]:
# 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
In [93]:
notlar.rename(index={"ogrenci37":"mehmet"},inplace=False)
Out[93]:
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

In [94]:
notlar['genel_ortalama'] = notlar['odev1']*0.1 + notlar['odev2']*0.1 + notlar['arasinav']*0.3 + notlar['final']*0.5
notlar['genel_ortalama']
Out[94]:
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.

In [95]:
notlar = notlar.fillna(0)
notlar['genel_ortalama'] = notlar['odev1']*0.1 + notlar['odev2']*0.1 + notlar['arasinav']*0.3 + notlar['final']*0.5
notlar
Out[95]:
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.

In [96]:
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']
Out[96]:
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.

In [97]:
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'
In [98]:
notlar
Out[98]:
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.

In [99]:
notlar.describe()
Out[99]:
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
In [100]:
notlar['durum'].describe()
Out[100]:
count     37
unique    12
top        A
freq       8
Name: durum, dtype: object
In [101]:
notlar.sort_values(by=["final","genel_ortalama"])
Out[101]:
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.

In [102]:
import numpy as np
notlar.select_dtypes(include=np.number).mean()
Out[102]:
odev1             91.567568
odev2             77.189189
arasinav          66.351351
final             64.162162
genel_ortalama    68.862162
dtype: float64
In [103]:
notlar[['odev1','odev2','arasinav','final','genel_ortalama']].median()
Out[103]:
odev1              95.0
odev2             100.0
arasinav           72.0
final              76.0
genel_ortalama     77.4
dtype: float64
In [104]:
notlar.select_dtypes(include=np.number).max()
Out[104]:
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.

In [105]:
notlar["durum"].value_counts()
Out[105]:
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.

In [106]:
notlar = notlar.astype({"durum":'category'})
notlar['durum'].dtype
Out[106]:
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.

In [107]:
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.

In [108]:
%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()
In [109]:
%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()
In [110]:
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.

In [111]:
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.

In [112]:
#notlar.options.display.float_format = '{:.2f}'.format
notlar['genel_ortalama'] = notlar['genel_ortalama'].map('{:.2f}'.format)
In [113]:
notlar.to_csv("ders_notlar_sonuc.csv")

Kaynaklar¶

  • 10 minutes to pandas
  • Pandas Dokümantasyonu
  • Real Python Pandas Tutorial
  • Python Data Science Handbook, Jake VanderPlas, 2017, O’Reilly Media, Inc.

Başa Dön