View on GitHub

Pandas-temel

Bu repoda Pandas'ın temel konusu anlatılmaktadır.

Pandas

Pandas nedir?

Pandas veri okuma, veri analizi ve veri temizlemede kullanılan açık kaynak kodlu python kütüphanesidir. Numpy alternatifi değildir, Numpy özelliklerini kullanıp genişletir.

Nasıl kurulur?

pip install pandas

Projeye entegre edilmesi

# Artık pandas kütüphanesi pd ile adlandırılacaktır.
import pandas as pd 

Pandas sürümünü kontrol etmek

pd.__version__
'1.3.5'

Pandas veri yapıları

Series

Seriler, etiketlerden (indeks) oluşan tek boyutlu bir veri yapısıdır.

Seri oluşturma

Pandas kütüphanesi içerisindeki Series methodunu kullanabilirz. Series methodu içerisine data vermemiz gerekmekte bu data değer, liste, Numpy dizisi veya sözlükler (dictionary) olabilir.

series = pd.Series([10, 20, 30, 40, 50])

print(series)
0    10
1    20
2    30
3    40
4    50
dtype: int64

**Bir etiket vermediğimizden için etiketlerimiz otomatik olarak 0’dan başlayarak atandı. **

Etiket (indeks) bilgileri

Serilerin etiket (indeks) bilgilerine erişmek için axes kullanılabilir.

series.axes
[RangeIndex(start=0, stop=5, step=1)]

Burada 0’dan başlayıp 5’e kadar gitmiş ve birer birer artmıştır

Değerler ile ilgili bilgi almak

Değerler ile ilgili bilgi almak istediğimizde dtype kullanabiliriz.

series.dtype
dtype('int64')

Öğe sayısını almak

series.size
5

Dizi şeklinde değerlere erişmek

Serileri dizi şeklinde değerlerine erişmek istersek values özelliğini kullanabiliriz. values özelliği serileri türüne bağlı olarak ndarray (Numpy array) şeklinde geri döndürür.

series.values
array([10, 20, 30, 40, 50])

İlk belirli bir elemana erişmek

Bir serinin ilk belirli elemanına erişmek istersek head methodunu kullanabiliriz. head methodu içerisine yazdığımız değer kadar elemanı bize geri döndürür.

series.head()
0    10
1    20
2    30
3    40
4    50
dtype: int64

Default değer 5 atandığı için head içerisine bir şey yazmadığımızda ilk 5 elemanı bizlere getirecektir.

series.head(3)
0    10
1    20
2    30
dtype: int64

Seri içerisindeki değerleri toplamak (sum)

Serimizin içerisindeki değerleri toplamak istersen sum methodunu kullanabiliriz.

summation = series.sum()

print(summation)
150

Seri içerisindeki en büyük değere ulaşmak (max)

Seri içerisinde en büyük değere ulaşmak için max methodunu kullanabiliriz.

maximum = series.max()

print(maximum)
50

Seri içerisindeki en küçük değere ulaşmak (min)

Seri içerisinde en küçük değere ulaşmak için min methodunu kullanabiliriz.

minimum = series.min()

print(minimum)
10

Serinin ortalamasını bulmak (mean)

Serinin ortalamasını bulmak için mean methodunu kullanabiliriz.

average = series.mean()

print(average)
30.0

Etiket isimlendirme

Etiket isimlendirme işleminde seri oluştururken Series methoduna bir index paramatresi göndererek etiketleme işlemini yapabiliriz.

series = pd.Series([11, 32, 45, 62, 71], index = [1, 3, 5, 7, 9])

print(series)
1    11
3    32
5    45
7    62
9    71
dtype: int64

Etiketleri elimizle index ifadesine verdiğimiz için artık serimizin etiketleri bizim verdiğimiz değerler olacaktır.

series = pd.Series([11, 32, 45, 62, 71], index = ["a", "b", "c", "d", "e"])

print(series)
a    11
b    32
c    45
d    62
e    71
dtype: int64

Etiket verme işleminde illa tam sayı olacak diye bir koşul yok string değer de verebiliriz.

Etikete göre elemana erişme

Serinin etiketine göre elemana erişmek istersek sözlük (dictionary) mantığını gibi kullanabiliriz.

series = pd.Series([11, 32, 45, 62, 71], index = ["a", "b", "c", "d", "e"])

first_element = series["a"] # ilk etiket "a" olduğu için bu şekilde kullandık
last_element = series["e"]

print(first_element)
print(last_element)
11
71

Serinin belirli bir aralığına erişme

Serinin belirli bir aralığına erişmek için kullanılan etikete göre elemana erişme işleminden sonra gidilecek yeri söyleyerek bir aralığa erişebiliriz.

series = pd.Series([11, 32, 45, 62, 71], index = ["a", "b", "c", "d", "e"])

intermittent_values = series["a": "c"] # dizinin "a" etiketinden "c" etiketi dahil olmak üzere belirlenen aralığı getirir

print(intermittent_values)
a    11
b    32
c    45
dtype: int64

İki seriyi birleştirme

İki seriyi birleştirmek için pandas kütüphanesinden concat methodu kullanılabilir. concat methodu kullanılırken içine verilecek değerleri bir listenin içerisinde yazmamız gerekmektedir.

series1 = pd.Series([11, 32, 45, 62, 71], index = ["a", "b", "c", "d", "e"])
series2 = pd.Series([1, 2, 3, 4, 5, 6])

compound_series = pd.concat([series1, series2])

print(compound_series)
a    11
b    32
c    45
d    62
e    71
0     1
1     2
2     3
3     4
4     5
5     6
dtype: int64

Serinin etiketlerine erişmek

Bir serinin etiketlerine erişmek istersek index özelliğini kullanabiliriz.

series = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"])

print(series.index)
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')

Serinin değerlerine erişmek

Bir serinin değerlerine erişmek istersek keys özelliğini kullanabiliriz.

series = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"])

print(series.keys)
<bound method Series.keys of a    1
b    2
c    3
d    4
e    5
dtype: int64>

Seriyi listeye dönüştürme

Bir seriyi listeye dönüştürmek istersek items methodu ile bir liste şekline sonra da list methodu ile listeye çevirebiliriz.

series = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"])

sample_list = list(series.items())

print(sample_list)
[('a', 1), ('b', 2), ('c', 3), ('d', 4), ('e', 5)]

Fancy ile elemana erişmek

series = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"])

sample_fancy = series[["a", "d"]]

print(sample_fancy)
a    1
d    4
dtype: int64

Serimizin içerisine istediğimiz değerleri liste şeklinde gönderip fancy yardımıyla bu değerlere erişmiş olduk.

Etiketin değerini değiştirmek

series = pd.Series([1, 2, 3, 4, 5], index = ["a", "b", "c", "d", "e"])

series["a"] = 10

print(series)
a    10
b     2
c     3
d     4
e     5
dtype: int64

Serimizin içerisindeki “a” değerine erişip bu değişkene 10 değeri ile değiştirme işlemi yaptık.

DataFrame

DataFrame veri çerçevesi anlamına gelir. Sql tablosuna benzer bir yapıdadır. DataFrameler veriyi daha kolay işleme imkanı sunar.

DataFrame oluşturma

Pandas kütüphanesinin içerisinde yer alan DataFrame ile oluşturulabilir. DataFrame içerisine bir data ve index gibi bir çok özellik alır. Eğer index değişkenine atama yapmazsak otomatik 0’dan başlayarak artar. Eğer columns değerini girersek oluşacak olan DataFrame yapısının column ismini ayarlar.

df = pd.DataFrame([10, 20, 30, 40, 50], columns=["column 1"])

df
column 1
0 10
1 20
2 30
3 40
4 50

DataFrame içerisindeki data parametresi yerine sözlük (Dictionary), Numpy dizisi veya başka bir DataFrame koyabiliriz.

DataFrame sütunları isimlendirmek

DataFrame kullanırken sütunlara erişmek veya bu sütunlarin isimlerini değiştirmek istediğimizde columns özelliğini kullanabiliriz.

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"])

print(df.columns) # DataFrame içerisinde yer alan sütunların isimlerini geri döndürür

print("-" * 30)
df.columns = ("sutün 1", "sütun 2", "sütun 3") # Sütünlar otomatik atadığımız değişkenlerle değiştir tekrar yeni bir değişkene atama işlemimize gerek yoktur.

df
Index(['column 1', 'column 2', 'column 3'], dtype='object')
------------------------------
sutün 1 sütun 2 sütun 3
0 10 20 30
1 1 2 3

Numpy dizilerini kullanarak iki boyutlu ve üç elemanlı bir dizi oluşturduk. Oluşan bu diziyi ise DataFrame data özelliği olarak verdik ve sütun isimlendirilmesi yaptık.

DataFrame içserisindeki değerleri çekme

DataFrame içerisinde değerleri çekmek için values özelliği kullanılabilir. Fakat values özelliği bir numpy dizisi geri döndürür.

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"])

print(df.values) # Diz içerisindeki verilere ulaşma işlemi
print("-" * 30)
print(type(df.values)) # ndarray şeklinde bir numpy dizisi geri döndürür
[[10 20 30]
 [ 1  2  3]]
------------------------------
<class 'numpy.ndarray'>

DataFrame index değiştirmek

DataFrame index değiştirme işlemi için index özelliğine yeni indeks değerleri atanabilir.

import numpy as np

arr1 = np.random.randint(10, size=5)
arr2 = np.random.randint(10, size=5)

dictionary = {
    "pro1" : arr1,
    "pro2" : arr2
}

# Sözlük kullanarak bir DataFrame oluşturduk.
df = pd.DataFrame(dictionary)

# DataFrame ilk hali
print(df)
print("-" * 30)

df.index = ["a", "b", "c", "d", "e"]

# DataFrame son hali
print(df)
   pro1  pro2
0     5     1
1     0     2
2     9     7
3     8     4
4     1     3
------------------------------
   pro1  pro2
a     5     1
b     0     2
c     9     7
d     8     4
e     1     3

DataFrame indeks ile satırlara erişmek

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3], [40, 50, 60]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"], index = ["a", "b", "c"])

rows = df["a": "b"]

rows
column 1 column 2 column 3
a 10 20 30
b 1 2 3

DataFrame içerisinden indekse göre satırlara erişmek istediğimizden bu şekilde kullanabiliriz.

DataFrame içerisinden satır silme

DataFrame içerisinden bir satırı silmek istediğimizde drop methodunu kullanabiliriz.

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3], [40, 50, 60]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"], index = ["a", "b", "c"])

print(df)
print("-" * 30)

# DataFrame içerisindeki etiketi "b" olan satırı silme işlemi.
df.drop("b", axis=0, inplace = True)

print(df)
   column 1  column 2  column 3
a        10        20        30
b         1         2         3
c        40        50        60
------------------------------
   column 1  column 2  column 3
a        10        20        30
c        40        50        60

drop methodunun ilk parametresi neyi silmek istediğimizi belirtir ikinci parametresi olan axis parametresini eğer 0 olarak atama yaparsak DataFrame içerisinde satırları belirtir, eğer axis parametresini 1 olarak atama yaparsak sütunları belirtir. drop fonksiyonun üçüncü parametresi olan inplace özelliği bizim değişiklik yaptığımız DataFrame üzerinde değişiklik yapılmasını kontrol eder. Varsayılan olarak inplace özelliği False olarak ayarlanmıştır yani bir satır silmek istediğimizde ve inplace özelliğine False değerini atamış olursak varsayılan DataFrame herhangi bir değişikliğe uğramayacaktır.

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3], [40, 50, 60]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"], index = ["a", "b", "c"])

print(df)
print("-" * 30)

# DataFrame içerisindeki etiketi "column 1" olan sütünu silme işlemi.
df.drop("column 1", axis=1, inplace = True)

print(df)
   column 1  column 2  column 3
a        10        20        30
b         1         2         3
c        40        50        60
------------------------------
   column 2  column 3
a        20        30
b         2         3
c        50        60

drop fonksiyonunun ilk parametresini neyi silmek istediğimizi verdik, ikinci parametrede satır mı sütun mu bunu belirttik (0 = Satır, 1 = sütun), üçüncü parametresinde ise DataFrame üzerinde bir değişiklik yapılacağını inplace özelliğini True atayarak yapmış olduk.

birden fazla satır veya sütun silme işlemi;

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3], [40, 50, 60]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"], index = ["a", "b", "c"])

print(df)
print("-" * 30)

# DataFrame içerisindeki etiketi "column 1" olan sütünu silme işlemi.
df.drop(["a", "b"], axis=0, inplace = True)

print(df)
   column 1  column 2  column 3
a        10        20        30
b         1         2         3
c        40        50        60
------------------------------
   column 1  column 2  column 3
c        40        50        60

Burada birden fazla satır silme işlemi yapmak için fancy kullandık yani drop methodumuza bu sefer tek bir elemanı sil demedik birden fazla elemani liste şeklinde gönderdik.

DataFrame içerisine yeni bir sütun oluşturmak

Listeye eleman ekleme yapısı gibi atama işlemi yapabiliriz.

import numpy as np

arr = np.array([[10, 20, 30], [1, 2, 3], [40, 50, 60]])

df = pd.DataFrame(arr, columns=["column 1", "column 2", "column 3"], index = ["a", "b", "c"])

print(df)
print("-" * 30)

df["column 4"] = df["column 1"] + df["column 2"]

print(df)
   column 1  column 2  column 3
a        10        20        30
b         1         2         3
c        40        50        60
------------------------------
   column 1  column 2  column 3  column 4
a        10        20        30        30
b         1         2         3         3
c        40        50        60        90

Burada “column 4” sütununu oluşturmak istiyoruz ve listeye eleman ekleme işlemi gibi uyguluyoruz.

DataFrame üzerinde veri seçme işlemleri

loc

import numpy as np

random_arr = np.random.randint(1, 100, size = (10, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

print(df)
print("-" * 30)

locate = df.loc[1:5]
locate
    a   b   c   d   e
0  92  36  44  64  23
1  14  72  81  54  21
2  48  53  30  79  71
3  10  46  97  33  60
4  76  65  67  57  14
5  32  79  30  72  58
6  70  85  16  28  22
7  90  42   7  64  58
8  19  91  47  35  35
9  93  51  93  70  99
------------------------------
a b c d e
1 14 72 81 54 21
2 48 53 30 79 71
3 10 46 97 33 60
4 76 65 67 57 14
5 32 79 30 72 58

Burada oluşturmuş olduğumuz 10 satırlı bir DataFrame içerisindeki 1. elemandan ve 5. elemana (dahil) kadar bir veri seçme işlemi gerçekleştirdik.

iloc

import numpy as np

random_arr = np.random.randint(1, 100, size = (10, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

print(df)
print("-" * 30)

locate = df.iloc[1:5]

locate
    a   b   c   d   e
0  74  69  85  53  58
1  32  25  53   6  10
2  65  57  87  21  34
3  27   6  74  67  85
4  39  44  92  84  22
5  43   1  90   4  36
6  42  68  33  45  47
7  83  97  36  69  11
8  20  57  64  16  53
9  35  56  99  85  29
------------------------------
a b c d e
1 32 25 53 6 10
2 65 57 87 21 34
3 27 6 74 67 85
4 39 44 92 84 22

iloc ile loc arasında aralıklı veri seçim farkı

iloc ile loc temel farkını satır ve sütun veri seçme işleminde göreceğiz.

loc kullandığımızda verdiğimiz aralığın ikisini de kapsar fakat iloc kullandığımızda verilen aralığın ilki dahil ikindisi dahil olmayaktır. Örneğim 5 satırlık bir DataFrame oluşturduk ve biz bu DataFrame içerisinden ilk 1. satırdan 3. satıra (dahil değil) kadar olan verilere erişmek istiyoruz. Burada iki farklı yolumuz vardır;

Eğer loc ile iloc aralığını aynı verirsek farkı daha iyi anlayabiliriz. Örnek olarak;

import numpy as np

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

# Oluşturduğumuz DataFrame
print("Oluşturduğumuz DataFrame")
print(df)
print("-" * 30)

# loc ile veriye erişmek
print("loc ile veriye erişmek")
locate = df.loc[1:3]
print(locate)
print("-" * 30)

# iloc ile veriye erişmek
print("iloc ile veriye erişmek")
locate = df.iloc[1:3]
print(locate)
print("-" * 30)
Oluşturduğumuz DataFrame
    a   b   c   d   e
0  45  51  99  74  73
1  90  79  79   6   5
2  10  23  80   3  62
3  75  30  17  59  64
4  66  82  80  78  94
------------------------------
loc ile veriye erişmek
    a   b   c   d   e
1  90  79  79   6   5
2  10  23  80   3  62
3  75  30  17  59  64
------------------------------
iloc ile veriye erişmek
    a   b   c  d   e
1  90  79  79  6   5
2  10  23  80  3  62
------------------------------

Burada gördüğünüz üzere loc ve iloc aralığını aynı verdiğimizde, loc son aralık değerini dahil etti fakat iloc dahil etmedi.

Satır ve sütun veri seçme işlemi

import numpy as np

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

locate = df.iloc[0:3, 0:2]
locate
a b
0 96 36
1 15 89
2 32 11

Burada veri seçme işlemi için dilersek iloc dilersek de loc kullanabiliriz. iloc veya loc içerisine verilen ilk aralık(0:3) satırları, ikinci aralık(0:2) ise sütunları temsil eder.

ÖNEMLİ

iloc ile direkt sütun işlemi yapılmaz indeks işlemi yapılır

Örneğin;

import numpy as np
import logging
import traceback

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

try:
  locate = df.iloc[0:3, "a"]
  print(locate)
except Exception as e:
  logging.error(traceback.format_exc())
ERROR:root:Traceback (most recent call last):
  File "/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py", line 754, in _has_valid_tuple
    self._validate_key(k, i)
  File "/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py", line 1426, in _validate_key
    raise ValueError(f"Can only index by location with a [{self._valid_types}]")
ValueError: Can only index by location with a [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array]

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "<ipython-input-37-4cd83f647b7b>", line 9, in <module>
    locate = df.iloc[0:3, "a"]
  File "/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py", line 925, in __getitem__
    return self._getitem_tuple(key)
  File "/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py", line 1506, in _getitem_tuple
    self._has_valid_tuple(tup)
  File "/usr/local/lib/python3.7/dist-packages/pandas/core/indexing.py", line 759, in _has_valid_tuple
    ) from err
ValueError: Location based indexing can only have [integer, integer slice (START point is INCLUDED, END point is EXCLUDED), listlike of integers, boolean array] types

Burada eğer bir aralık vermeyip istediğimiz satırı veya sütunun değerini verirsek indeks bazlı veri seçmek olacak fakat iloc index bazlı seçim yapamaz burada iloc yerine loc kullanabiliriz.

import numpy as np
import logging
import traceback

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

try:
  locate = df.loc[0:3, "a"]
  print(locate)
except Exception as e:
  logging.error(traceback.format_exc())
0    24
1    21
2    89
3    56
Name: a, dtype: int64

Burada direkt bir sütunun değerini veya satırın değerini verdiğimiz için loc ifadesi ile veri seçme işlemimizi gerçekleştirmiş olduk

####iloc ile sütun seçme işlemi

import numpy as np

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

locate = df.iloc[0:3]["a"]

locate
0    90
1    95
2    24
Name: a, dtype: int64

Burada iloc ile sütun seçme işlemi yaptık burada satır olarak 0’dan 3’e kadar olan satırları seçtik ve bu satırladın da sahip olduğu a sütununu aldık.

Birden fazla sütun seçmek istersek fancy kullanabiliriz. Örneğin;

import numpy as np

random_arr = np.random.randint(1, 100, size = (5, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

locate = df.iloc[0:3][["a", "d", "e"]]

locate
a d e
0 76 53 88
1 94 17 64
2 33 37 60

Burada fancy yardımıyla birden fazla sütun seçme işlemini yapabildik.

Koşullu eleman seçme işlemi

import numpy as np

random_arr = np.random.randint(1, 30, size = (10, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

df[df.a > 15]
a b c d e
0 27 28 19 16 19
2 21 12 7 1 21
4 17 2 28 5 15
5 17 2 13 25 29
6 25 21 3 28 26
7 19 17 17 6 18

Burada a sütunundaki değerlerin 15’den büyük olma koşulunu verdik. DataFrame içerisindeki sütuna erişmek için df.a ifadesini kullandık.

Birden fazla koşul girmek;

import numpy as np

random_arr = np.random.randint(1, 30, size = (10, 5))
df = pd.DataFrame(random_arr, columns=["a", "b", "c", "d", "e"])

df[(df.a > 15) & (df.d > 5)]
a b c d e
8 28 4 25 13 10

Burada a sütunundaki değerlerin 15’den büyük olduğu ve d sütunundaki değerlerin 5’den büyük olduğu değerleri aldık.

DataFrame sütunları değiştirmek

DataFrame içerisindeki sütunları değiştirmek istersek columns kullanabiliriz.

import numpy as np

random_arr = np.random.randint(1, 30, size = (5, 3))
df = pd.DataFrame(random_arr, columns=["a", "b", "c"])

df.columns = ["A", "B", "C"]

df
A B C
0 22 25 19
1 10 16 15
2 16 19 29
3 21 9 26
4 15 6 12

DataFrame birleştirme işlemleri (concat)

DataFrame birleştirme işlemleri için concat methodunu kullanabiliriz

import numpy as np

random_arr = np.random.randint(1, 30, size = (5, 3))
df1 = pd.DataFrame(random_arr, columns=["a", "b", "c"])
df2 = df1 * 2 # Oluşturulan df1 değerini 2 ile çarpıp df2 değişkenine atanma işlemi

print("Oluşturulan ilk DataFrame")
print(df1)
print("-" * 30)
print("Oluşturulan ikinci DataFrame")
print(df2)
print("-" * 30)

concat_df = pd.concat([df1, df2])
print("df1 ve df2 DataFrame birleştirme işlemi")
print(concat_df)
Oluşturulan ilk DataFrame
    a   b   c
0  19  22  10
1  11  28   3
2  28  23  17
3  24  15  25
4  11   9   5
------------------------------
Oluşturulan ikinci DataFrame
    a   b   c
0  38  44  20
1  22  56   6
2  56  46  34
3  48  30  50
4  22  18  10
------------------------------
df1 ve df2 DataFrame birleştirme işlemi
    a   b   c
0  19  22  10
1  11  28   3
2  28  23  17
3  24  15  25
4  11   9   5
0  38  44  20
1  22  56   6
2  56  46  34
3  48  30  50
4  22  18  10

Burada indeksleri birleştirme işlemi sonrasında indeksleri incelediğimizde bir hata görüyoruz. İndeksler 0’dan başlayıp 5’e kadar ilerlemiş fakat tekrar 0’dan başlayıp 5’e kadar ilerlemiş.

Bu sorunu çözmek için;

import numpy as np

random_arr = np.random.randint(1, 30, size = (5, 3))
df1 = pd.DataFrame(random_arr, columns=["a", "b", "c"])
df2 = df1 * 2 # Oluşturulan df1 değerini 2 ile çarpıp df2 değişkenine atanma işlemi

print("Oluşturulan ilk DataFrame")
print(df1)
print("-" * 30)
print("Oluşturulan ikinci DataFrame")
print(df2)
print("-" * 30)

concat_df = pd.concat([df1, df2], ignore_index=True)
print("df1 ve df2 DataFrame birleştirme işlemi")
print(concat_df)
Oluşturulan ilk DataFrame
    a   b   c
0   3  16  20
1   9   5  13
2  15  17  14
3  20   8  14
4   2   1  28
------------------------------
Oluşturulan ikinci DataFrame
    a   b   c
0   6  32  40
1  18  10  26
2  30  34  28
3  40  16  28
4   4   2  56
------------------------------
df1 ve df2 DataFrame birleştirme işlemi
    a   b   c
0   3  16  20
1   9   5  13
2  15  17  14
3  20   8  14
4   2   1  28
5   6  32  40
6  18  10  26
7  30  34  28
8  40  16  28
9   4   2  56

Burada concat methodunun içerisine ignore_index parametresine True atadığımızda indeks problemimiz ortadan kalktı.

Farklı sütünlara sahip olan DataFrame birleştirme işlemi

import numpy as np

random_arr = np.random.randint(1, 30, size = (5, 3))
df1 = pd.DataFrame(random_arr, columns=["a", "b", "c"])
random_arr = np.random.randint(1,30, size = (5,3))
df2 = pd.DataFrame(random_arr, columns=["Column 1", "Column 2", "c"])

pd.concat([df1, df2],  ignore_index=True)
a b c Column 1 Column 2
0 29.0 20.0 3 NaN NaN
1 21.0 2.0 21 NaN NaN
2 9.0 2.0 1 NaN NaN
3 15.0 21.0 5 NaN NaN
4 22.0 4.0 5 NaN NaN
5 NaN NaN 26 12.0 20.0
6 NaN NaN 11 17.0 10.0
7 NaN NaN 3 7.0 7.0
8 NaN NaN 29 11.0 7.0
9 NaN NaN 16 13.0 10.0

Burada görülen NaN ifadeleri birinci DataFrame ile ikinci DataFrame eşleşmediğinden ortaya çıkmıştır. Görüldüğü gibi sütun c iki DataFramede eşleştiği için otomatik c ifadesinin bulunduğu sütuna yazılmıştır.

pd.concat([df1, df2], join="inner", ignore_index=True)
c
0 3
1 21
2 1
3 5
4 5
5 26
6 11
7 3
8 29
9 16

Burada iki DataFramede ortak sütun olanları birleştirdik.

İleri Birleştirme işlemleri (merge)

Birebir (one to one) birleştirme

students = {
    "name": ["Furkan", "Özlem", "Kardem", "Doga"],
    "department": ["Bilgisayar", "Kimya", "Yazılım", "Yazılım"]
}

student_department = pd.DataFrame(students)

student_department
name department
0 Furkan Bilgisayar
1 Özlem Kimya
2 Kardem Yazılım
3 Doga Yazılım
graduation = {
    "name" : ["Furkan", "Özlem", "Kardem", "Doga"],
    "year" : ["2023", "2023", "2024", "2021"]
}

graduation_year = pd.DataFrame(graduation)

graduation_year
name year
0 Furkan 2023
1 Özlem 2023
2 Kardem 2024
3 Doga 2021
pd.merge(student_department, graduation_year)
name department year
0 Furkan Bilgisayar 2023
1 Özlem Kimya 2023
2 Kardem Yazılım 2024
3 Doga Yazılım 2021

student_department ile graduation_year DataFramelerimizi birleştirmek istedik ve merge ifadesi kullanılarak bu işlemi gerçekleştirdik. merge methodou otomatik olarak ortak olan sütuna göre birleştirme işlemi yapar.

Çoktan teke (many to one) birleştirme işlemi

students = {
    "name": ["Furkan", "Özlem", "Kardem", "Doga"],
    "department": ["Bilgisayar", "Kimya", "Yazılım", "Yazılım"]
}

graduation = {
    "name" : ["Furkan", "Özlem", "Kardem", "Doga"],
    "year" : ["2023", "2023", "2024", "2021"]
}

student_department = pd.DataFrame(students)
graduation_year = pd.DataFrame(graduation)

school = pd.merge(student_department, graduation_year)
school
name department year
0 Furkan Bilgisayar 2023
1 Özlem Kimya 2023
2 Kardem Yazılım 2024
3 Doga Yazılım 2021
department = {
    "department" : ["Bilgisayar", "Yazılım", "Kimya"],
    "head" : ["Raif", "Volkan", "Asım"]
}

department_heads = pd.DataFrame(department)

department_heads
department head
0 Bilgisayar Raif
1 Yazılım Volkan
2 Kimya Asım
pd.merge(school, department_heads)
name department year head
0 Furkan Bilgisayar 2023 Raif
1 Özlem Kimya 2023 Asım
2 Kardem Yazılım 2024 Volkan
3 Doga Yazılım 2021 Volkan

Burada bölümün başkanlarını belirten bir DataFrame oluşuturduk. Bu DataFrame ile daha önceden Öğrenci-Bölüm DataFrame ve Öğrenci-Mezuniyet yılını birleştirdiğimiz DataFrame ile birleştirme işlemi yaptık. Burada department her ikisi için olduğundan otomatik olarak birleştirme işlemi gerçekleşti. Görüleceği gibi yazılım bölümünün birden fazla bulunmaktadır.

Çoktan çoka (many to many) birleştirme

students = {
    "name": ["Furkan", "Özlem", "Kardem", "Doga"],
    "department": ["Bilgisayar", "Kimya", "Yazılım", "Yazılım"]
}

graduation = {
    "name" : ["Furkan", "Özlem", "Kardem", "Doga"],
    "year" : ["2023", "2023", "2024", "2021"]
}

student_department = pd.DataFrame(students)
graduation_year = pd.DataFrame(graduation)

school = pd.merge(student_department, graduation_year)
school
name department year
0 Furkan Bilgisayar 2023
1 Özlem Kimya 2023
2 Kardem Yazılım 2024
3 Doga Yazılım 2021
department = {
    "department" : ["Bilgisayar", "Yazılım", "Kimya"],
    "head" : ["Raif", "Volkan", "Asım"]
}

department_heads = pd.DataFrame(department)

department_heads
department head
0 Bilgisayar Raif
1 Yazılım Volkan
2 Kimya Asım
departments = pd.merge(school, department_heads)

departments
name department year head
0 Furkan Bilgisayar 2023 Raif
1 Özlem Kimya 2023 Asım
2 Kardem Yazılım 2024 Volkan
3 Doga Yazılım 2021 Volkan
department_skills = {
    "department" : ["Bilgisayar", "Bilgisayar", "Kimya", "Yazılım", "Yazılım"],
    "skills" : ["Kodlama", "Linux", "Çözelti hazırlama", "Kodlama", "Database"]
}

skills = pd.DataFrame(department_skills)

skills
department skills
0 Bilgisayar Kodlama
1 Bilgisayar Linux
2 Kimya Çözelti hazırlama
3 Yazılım Kodlama
4 Yazılım Database
pd.merge(departments, skills)
name department year head skills
0 Furkan Bilgisayar 2023 Raif Kodlama
1 Furkan Bilgisayar 2023 Raif Linux
2 Özlem Kimya 2023 Asım Çözelti hazırlama
3 Kardem Yazılım 2024 Volkan Kodlama
4 Kardem Yazılım 2024 Volkan Database
5 Doga Yazılım 2021 Volkan Kodlama
6 Doga Yazılım 2021 Volkan Database

Burada department_skills tablosunda olan bölümün yetenekleri belirtilmiştir. Bu tablo ile departments tablosundaki verileri birleştirme işlemi uyguladık. Son çıkan tablomuzda bir departman birden fazla yeteneğe sahip olabileceğinden bir kişiden iki tane görüyoruz.

Toplulaştırma (Aggregation)

import seaborn as sns

seaborn kütüphanesi içindeki hazır verisetlerini kullanacağız.

df = sns.load_dataset("planets")
df.head()
method number orbital_period mass distance year
0 Radial Velocity 1 269.300 7.10 77.40 2006
1 Radial Velocity 1 874.774 2.21 56.95 2008
2 Radial Velocity 1 763.000 2.60 19.84 2011
3 Radial Velocity 1 326.030 19.40 110.62 2007
4 Radial Velocity 1 516.220 10.50 119.47 2009

seaborn kütüphanesindeki “planets” verisetini değişkenimize atıyoruz ve ekrana bastırıyoruz.

df.shape
(1035, 6)

Yüklediğimiz datasetinde 1035 satır ve 6 sütun var olduğunu gözlemledik.

df.count()
method            1035
number            1035
orbital_period     992
mass               513
distance           808
year              1035
dtype: int64

Her bir sütündan kaç tane olduğunu belirten count methodunu kullandık.

df.mean()
/usr/local/lib/python3.7/dist-packages/ipykernel_launcher.py:1: FutureWarning: Dropping of nuisance columns in DataFrame reductions (with 'numeric_only=None') is deprecated; in a future version this will raise TypeError.  Select only valid columns before calling the reduction.
  """Entry point for launching an IPython kernel.





number               1.785507
orbital_period    2002.917596
mass                 2.638161
distance           264.069282
year              2009.070531
dtype: float64

Her bir sütunun ortalamasını belirten mean methodunu kullandık.

Eğer tek bir sütunun ortalamasını almak istersek;

df["number"].mean()
1.7855072463768116

Burada ise sadece number sütununun ortalamasını aldık.

df.describe()
number orbital_period mass distance year
count 1035.000000 992.000000 513.000000 808.000000 1035.000000
mean 1.785507 2002.917596 2.638161 264.069282 2009.070531
std 1.240976 26014.728304 3.818617 733.116493 3.972567
min 1.000000 0.090706 0.003600 1.350000 1989.000000
25% 1.000000 5.442540 0.229000 32.560000 2007.000000
50% 1.000000 39.979500 1.260000 55.250000 2010.000000
75% 2.000000 526.005000 3.040000 178.500000 2012.000000
max 7.000000 730000.000000 25.000000 8500.000000 2014.000000

Burada count, mean, std, min, 25%, 50%, 75% ve max methodlarını her bir sütun için uygulanmış tabloyu görüyoruz.

df.describe().T
count mean std min 25% 50% 75% max
number 1035.0 1.785507 1.240976 1.000000 1.00000 1.0000 2.000 7.0
orbital_period 992.0 2002.917596 26014.728304 0.090706 5.44254 39.9795 526.005 730000.0
mass 513.0 2.638161 3.818617 0.003600 0.22900 1.2600 3.040 25.0
distance 808.0 264.069282 733.116493 1.350000 32.56000 55.2500 178.500 8500.0
year 1035.0 2009.070531 3.972567 1989.000000 2007.00000 2010.0000 2012.000 2014.0

Okunabilirliği arttırmak adına describe methodunun transpozunu aldık.

df.dropna()
method number orbital_period mass distance year
0 Radial Velocity 1 269.30000 7.100 77.40 2006
1 Radial Velocity 1 874.77400 2.210 56.95 2008
2 Radial Velocity 1 763.00000 2.600 19.84 2011
3 Radial Velocity 1 326.03000 19.400 110.62 2007
4 Radial Velocity 1 516.22000 10.500 119.47 2009
... ... ... ... ... ... ...
640 Radial Velocity 1 111.70000 2.100 14.90 2009
641 Radial Velocity 1 5.05050 1.068 44.46 2013
642 Radial Velocity 1 311.28800 1.940 17.24 1999
649 Transit 1 2.70339 1.470 178.00 2013
784 Radial Velocity 3 580.00000 0.947 135.00 2012

498 rows × 6 columns

Burada verisetimizde var olan verilerden eksik olanları çıkarttık ve ortaya 784 sütun çıktı.

Toplulaştırma başlığı altında verilen methodları kendiniz kullanabilirsiniz.

Gruplama (groupby)

data = {
    "Class" : ["a", "b", "c", "a", "b", "c"],
    "student exam result" : [20, 13, 32, 40, 32, 11]
}

df = pd.DataFrame(data, columns = ["Class", "student exam result"])
df
Class student exam result
0 a 20
1 b 13
2 c 32
3 a 40
4 b 32
5 c 11

Burada sınıflar ve sınıflardaki herhangi bir kişinin aldığı not belirtilmektedir. Herhangi bir sınıf için bakılmak istenirse groupby kullanılabilir.

df.groupby("Class").mean()
student exam result
Class
a 30.0
b 22.5
c 21.5

Burada ise gruplanan sınıflara göre ortalama notu görmekteyiz.

df.groupby("Class").sum()
student exam result
Class
a 60
b 45
c 43

Burada ise gruplanan sınıflardaki öğrencilerin toplam notlarını görmekteyiz.

Toplulaştırmada kullanılan veriseti üzerinde gruplama;

import seaborn as sns

df = sns.load_dataset("planets")
df
method number orbital_period mass distance year
0 Radial Velocity 1 269.300000 7.10 77.40 2006
1 Radial Velocity 1 874.774000 2.21 56.95 2008
2 Radial Velocity 1 763.000000 2.60 19.84 2011
3 Radial Velocity 1 326.030000 19.40 110.62 2007
4 Radial Velocity 1 516.220000 10.50 119.47 2009
... ... ... ... ... ... ...
1030 Transit 1 3.941507 NaN 172.00 2006
1031 Transit 1 2.615864 NaN 148.00 2007
1032 Transit 1 3.191524 NaN 174.00 2007
1033 Transit 1 4.125083 NaN 293.00 2008
1034 Transit 1 4.187757 NaN 260.00 2008

1035 rows × 6 columns

Burada method sütunu bir kategorik değişken olduğu için bu sütunu gruplayabiliriz.

Tek bir sütun için toplulaştırma;

df.groupby("method")["number"].describe()
count mean std min 25% 50% 75% max
method
Astrometry 2.0 1.000000 0.000000 1.0 1.0 1.0 1.00 1.0
Eclipse Timing Variations 9.0 1.666667 0.500000 1.0 1.0 2.0 2.00 2.0
Imaging 38.0 1.315789 0.933035 1.0 1.0 1.0 1.00 4.0
Microlensing 23.0 1.173913 0.387553 1.0 1.0 1.0 1.00 2.0
Orbital Brightness Modulation 3.0 1.666667 0.577350 1.0 1.5 2.0 2.00 2.0
Pulsar Timing 5.0 2.200000 1.095445 1.0 1.0 3.0 3.00 3.0
Pulsation Timing Variations 1.0 1.000000 NaN 1.0 1.0 1.0 1.00 1.0
Radial Velocity 553.0 1.721519 1.157141 1.0 1.0 1.0 2.00 6.0
Transit 397.0 1.954660 1.399119 1.0 1.0 1.0 2.00 7.0
Transit Timing Variations 4.0 2.250000 0.500000 2.0 2.0 2.0 2.25 3.0

Burada method sütununu gruplaştırdık ve bu gruplaştırmadan sonra number sütününün describe methodunu çağırdık.

İleri toplulaştırma işlemleri (aggregate, filter, transform, apply)

Kullanacağımız veriseti;

import pandas as pd
import numpy as np

dictionary = {
    "class" : ["a", "b", "c", "a", "b", "c"],
    "students_id" : [35, 27, 15, 41, 80, 9],
    "exam_result" : [100, 20, 40, 50, 14, 90]
}

df = pd.DataFrame(dictionary)

df
class students_id exam_result
0 a 35 100
1 b 27 20
2 c 15 40
3 a 41 50
4 b 80 14
5 c 9 90

Aggregate

df.groupby("class").aggregate(["min", np.median, "max"])
students_id exam_result
min median max min median max
class
a 35 38.0 41 50 75.0 100
b 27 53.5 80 14 17.0 20
c 9 12.0 15 40 65.0 90

Burada verisetimizi class sütununa göre grupladık ve sonrasında aggregate methodu ile bu gruplanan tablodan min, median ve max değerletini getirdik.

query = {
    "students_id" : np.median,
    "exam_result" : ["min", "max"] 
}

df.groupby("class").aggregate(query)
students_id exam_result
median min max
class
a 38.0 50 100
b 53.5 14 20
c 12.0 40 90

Burada farklı sütunlara farklı işlemler uyguladık. students_id sütununa median işlemini exam_result sütununa da min ve max işlemini uyguladık

Filter

Kendi yazdığımız fonksiyonlarımızı DataFrame üzerinde filtrelemeye yarar.

def filter_func(df):
  return df["exam_result"].std() > 9
df.groupby("class").filter(filter_func)
class students_id exam_result
0 a 35 100
2 c 15 40
3 a 41 50
5 c 9 90

Burada class sütununa göre bir gruplama işlemi yaptık. Bu sütunlama işleminin ardından kendi yazdığımız fonksiyona göre filtreleme işlemi yaptık. Burada fonksiyonumuz exam_result tablosundaki standart sapması 9 dan büyük olanları geri döndürdü.

Transform

Değişkenlerin hepsinde gezip istediğimiz fonksiyonu uygulayan method.

change_df = df.iloc[:, 1:3]

change_df.transform(lambda value: value - value.mean())
students_id exam_result
0 0.5 47.666667
1 -7.5 -32.333333
2 -19.5 -12.333333
3 6.5 -2.333333
4 45.5 -38.333333
5 -25.5 37.666667

Burada class sütunu bir kategorik değişken olduğundan dolayı, biz bu sütunu almayıp yeni bir değişkene atıyoruz. Ardından değerlerden değerlerin ortalamasını çıkaran bir fonksiyon yazdık.

Apply

DataFramedeki değişkenlerin üzerinde gezen ve toplulaştırma amacıyla kullanılan method.

change_df = df.iloc[:, 1:3]

change_df
students_id exam_result
0 35 100
1 27 20
2 15 40
3 41 50
4 80 14
5 9 90

Burada class olan sütunumuzu almayıp students_id ve exam_result sütununu farklı bir değişkene atadık.

change_df.apply(np.sum)
students_id    207
exam_result    314
dtype: int64

Burada değerlerin üzerinde gezip students_id ve exam_result değerlerinin toplamını buldu.