Ana sayfa Python Groupby Kullanımı
Gönderi
İptal

Python Groupby Kullanımı

Pandas paketi veri analizi ve işlemesi için hazırlanmış bir Python paketidir. Bu paket çeşitli formatlardaki dosyaları (Excel, Csv, Txt gibi) okumayı, bu formatlarda dosyalar oluşturmayı kolaylaştırır. Aynı zamanda pandas paketi ile oluşturulan veri çerçeveleri (dataframe) sayesinde farklı formatlardaki (sayı, metin, tarih) veriyi birlikte tutmak, bu verileri işlemek ve basit analizler yapmak mümkündür.

Pandas paketinin altındaki bir yöntem olan groupby() ham haldeki veriden (örnek olarak alışveriş verisi) çeşitli istatistikler çıkarmak için oldukça yararlı bir araç. Bu Veri Defteri’nde UCI Machine Learning Repository’de bulunan online satış verisini kullanacağız. İlk olarak veriyi okutarak ve boyutlarına bakarak başlayalım. Veriyi indirmek için tıklayınız.

In [1]:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# İlk adımda pandas ve numpy paketlerini yüklüyoruz

import pandas as pd
import numpy as np
from IPython.display import display, HTML

# Input dosyasının olduğu klasörün yolu
IDIR = 'D:/Data/Blog/Data/'

# Pandas'ın altındaki read_excel fonksiyonuyla Excel dosyasını okutabiliriz.
# Pandas aynı zamanda csv, table, sql ve kopyaladığınız tablo halindeki verileri de okuyabilir (clipboard).
# read_csv, read_table, read_json, read_sql, read_clipboard fonksiyonlarını inceleyebilirsiniz.
# Şimdi veriyi okutarak verinin boyutlarını inceleyelim.

df = pd.read_excel(IDIR + 'Online Retail.xlsx')

print("Veri çerçevesinin boyutu: " + str(np.shape(df)))
1
Veri çerçevesinin boyutu: (541909, 8)

Veride 8 kolon var. Kolonlar hakkındaki ilk bilgiyi head() fonksiyonuyla görebiliriz.

In [2]:

1
2
HTML(df.head().to_html()) #bu satır sorunlu olduğu için aşağıdaki satırla alabilirsiniz.
display(df)

Out[2]:

 InvoiceNoStockCodeDescriptionQuantityInvoiceDateUnitPriceCustomerIDCountry
053636585123AWHITE HANGING HEART T-LIGHT HOLDER62010-12-01 08:26:002.5517850.0United Kingdom
153636571053WHITE METAL LANTERN62010-12-01 08:26:003.3917850.0United Kingdom
253636584406BCREAM CUPID HEARTS COAT HANGER82010-12-01 08:26:002.7517850.0United Kingdom
353636584029GKNITTED UNION FLAG HOT WATER BOTTLE62010-12-01 08:26:003.3917850.0United Kingdom
453636584029ERED WOOLLY HOTTIE WHITE HEART.62010-12-01 08:26:003.3917850.0United Kingdom

Verideki kolonların ne anlama geldiğine bakalım.

KolonAnlam
InvoiceNoFatura numarası, her alışverişin bir numarası var
StockCodeÜrünün numarası
DescriptionÜrünün açıklaması
QuantityÜründen kaç adet alındığı
InvoiceDateAlışverişin tarihi ve saati
UnitPriceÜrünün birim fiyatı
CustomerIDMüşteri numarası
CountryÜlke

Öncelikle ülke bazında alışveriş istatistikleri çıkaralım. Bu amaçla ilk yapacağımız şey veri setini ülke bazında gruplamak.

In [3]:

1
2
# Veriyi ülke (Country) bazında grupluyoruz
df_country = df.groupby('Country')

Veride hangi ülkeler olduğunu görmek için group.keys(), kaç ülke olduğunu görmek içinse ngroups metotlarını kullanabiliriz.

In [4]:

1
2
3
print("Ülkeler")
print(df_country.groups.keys())
print("Ülke sayısı: " + str(df_country.ngroups))
1
2
3
4
5
Ülkeler

dict_keys(['Australia', 'Austria', 'Bahrain', 'Belgium', 'Brazil', 'Canada', 'Channel Islands', 'Cyprus', 'Czech Republic', 'Denmark', 'EIRE', 'European Community', 'Finland', 'France', 'Germany', 'Greece', 'Hong Kong', 'Iceland', 'Israel', 'Italy', 'Japan', 'Lebanon', 'Lithuania', 'Malta', 'Netherlands', 'Norway', 'Poland', 'Portugal', 'RSA', 'Saudi Arabia', 'Singapore', 'Spain', 'Sweden', 'Switzerland', 'USA', 'United Arab Emirates', 'United Kingdom', 'Unspecified'])

Ülke sayısı: 38

Veri setinde 38 ülkeden yapılan alışverişler var. Her bir gruba (ülkede yapılan alışverişlere) erişmek için aşağıdaki gibi bir loop kullanabiliriz. df_country bir GroupBy objesi ve veriyi ülke ve satış verisini içeren bir dictionarye benzer bir şekilde tutuyor.

In [5]:

1
2
3
for country, sales in df_country:
    if country == 'Belgium':
        HTML(sales.head().to_html())

İstediğimiz gruba ulaşmanın bir diğer yolu da get_group() fonksiyonu. ‘Austria’ için olan satış verilerine ulaşmayı deneyelim.

In [6]:

1
HTML(df_country.get_group('Austria').head().to_html())

Out[6]:

 InvoiceNoStockCodeDescriptionQuantityInvoiceDateUnitPriceCustomerIDCountry
31464C53897122153ANGEL DECORATION STARS ON DRESS-482010-12-15 11:39:000.4212865.0Austria
3429353933037449CERAMIC CAKE STAND + HANGING CAKES82010-12-17 09:38:008.5012370.0Austria
3429453933037446MINI CAKE STAND WITH HANGING CAKES82010-12-17 09:38:001.4512370.0Austria
3429553933022962JAM JAR WITH PINK LID122010-12-17 09:38:000.8512370.0Austria
3429653933021428SET3 BOOK BOX GREEN GINGHAM FLOWER42010-12-17 09:38:004.2512370.0Austria

Şimdi her ülke için en çok satılan ürünü bulalım. Bunun için yapmamız gerekenler ülke (Country) ve ürün (StockCode) bazında satış miktarlarını (Quantity) toplamak olacak. Ondan sonra da her ülke için en çok satılan ürünü bulacağız. groupby fonksiyonuna vereceğimiz by argümanı hangi kolonlara göre (Country, StockCode) gruplayacağımız bilgisini veriyor. Daha sonra işlem yapacağımız kolonu (Quantity) ve yapacağımız işlemi (sum()) belirtiyoruz.

In [7]:

1
2
df_country_product = df.groupby(by = ['Country', 'StockCode'])['Quantity'].sum()
print(df_country_product.head())
1
2
3
4
5
6
7
8
9
10
11
12
13
Country    StockCode

Australia  15036        600

           20665          6

           20675        216

           20676        216

           20677        216

Name: Quantity, dtype: int64

Dataframe yapısını korumak için reset_index() fonksiyonunu kullanabiliriz.

In [8]:

1
2
df_country_product = df_country_product.reset_index()
HTML(df_country_product.head().to_html())

Out[8]:

 CountryStockCodeQuantity
0Australia15036600
1Australia206656
2Australia20675216
3Australia20676216
4Australia20677216

Ülke bazında en yüksek miktara sahip ürünleri bulmak için groupbyı maksimum değeri bulacak şekilde kullanabiliriz. Ancak bu ürün bilgisini vermeyeceği için transform yöntemini kullanıyoruz. Bu sayede her ülke için maksimum satış değerine sahip ürünün satış adedine erişiyoruz. Aşağıdaki satırda değeri maksimum satışa sahip ürünlere sahip indexleri belirliyoruz. Bu, aynı satış miktarına sahip birden fazla ürün varsa onları da bulmamızı sağlar.

In [9]:

1
2
3
idx = df_country_product.groupby(['Country'])['Quantity'].transform(max) == df_country_product['Quantity']

HTML(df_country_product[idx].head(10).to_html())

Out[9]:

 CountryStockCodeQuantity
221Australia224922916
671Austria21918288
914Bahrain2307696
1005Belgium21212480
1705Brazil2143024
1714Brazil2263024
1716Brazil2269724
1717Brazil2269824
1718Brazil2269924
1719Brazil2272224

Şimdi de müşteriler için çeşitli istatistikler çıkaralım. Müşterilerle ilgili pazarlama, segmentasyon, müşteri terki tahmini gib çalışmalarda sıklıkla kullanılan RFM (Recency, frequency, monetary / yakınlık, sıklık, mali) değişkenlerini groupby fonksiyonunu kullanarak oluşturacağız. Bu tip istatistikler aynı zamanda gerçekleştireceğiniz çalışmalarda öznitelik türetmek için de kullanılabilir.

Her müşteri için aşağıdaki değişkenlerin değerlerini elde etmek istiyoruz:

  • Alışveriş sayısı
  • Toplam ve ortalama alışveriş miktarı
  • Satın alınan toplam ve ortalama (farklı) ürün sayısı
  • En son alışveriş tarihi

Bunun için öncelike toplam alışveriş miktarını ‘Amount’ kolonuna yazdıracağız. Yapmamız gereken miktar (Quantity) ile birim fiyat (UnitPrice) kolonlarını çarpmak.

Bunları yapmadan önce müşteri (CustomerID) kolonunda boş değerler olduğu için öncelikle bu alışverişleri veri setinden çıkaralım.

In [10]:

1
2
3
4
5
6
7
8
9
10
# CustomerID değeri olmayan müşterileri veri setinden çıkaralım.

print("Temizlik öncesi alışveriş sayısı: " + str(len(df)))
df = df[df['CustomerID'] > 0]
print("Temizlik sonrası alışveriş sayısı: " + str(len(df)))

# Birim fiyat ve miktar değerlerini çarparak toplam tutarı bulalım.

df['Amount'] = df['Quantity'] * df['UnitPrice']
HTML(df.head().to_html())
1
2
3
Temizlik öncesi alışveriş sayısı: 541909

Temizlik sonrası alışveriş sayısı: 406829

Out[10]:

 InvoiceNoStockCodeDescriptionQuantityInvoiceDateUnitPriceCustomerIDCountryAmount
053636585123AWHITE HANGING HEART T-LIGHT HOLDER62010-12-01 08:26:002.5517850.0United Kingdom15.30
153636571053WHITE METAL LANTERN62010-12-01 08:26:003.3917850.0United Kingdom20.34
253636584406BCREAM CUPID HEARTS COAT HANGER82010-12-01 08:26:002.7517850.0United Kingdom22.00
353636584029GKNITTED UNION FLAG HOT WATER BOTTLE62010-12-01 08:26:003.3917850.0United Kingdom20.34
453636584029ERED WOOLLY HOTTIE WHITE HEART.62010-12-01 08:26:003.3917850.0United Kingdom20.34

Alışverişleri önce müşteri (CustomerID) ve alışveriş (InvoiceNo) değerleri için gruplayalım. Bu sayede her alışveriş için sepetteki ürün sayısı ve sepetteki ürünleri toplam tutarını öğrenebiliriz. Her alışveriş için yapacağımız işlemler aşağıdakilerdir:

  • Farklı ürün sayısını bulmak (StockCode): Kullanacağımız yöntem nunique kaç tane tekil (unique) değer olduğuna bakar.
  • Sepetteki ürünlerin değerini toplamak (Amount): Kullanacağımız yöntem sum verilen kolonun değerlerini toplar.
  • Alışveriş tarihini belirlemek (InvoiceDate): Kullanacağımız değer max maksimum değeri verir. Burada max değerini kullanmamız şart değil. Sadece bu değeri bir sonraki tabloya da aktarmak istiyoruz.

agg fonksiyonu dictionary yapısıyla bu farklı işlemleri tek satırda yapmamıza imkan tanıyor.

In [11]:

1
2
3
4
5
6
7
df_customer = df.groupby(['CustomerID', 'InvoiceNo']).agg({'StockCode':'nunique',
                                                           'Amount':'sum',
                                                           'InvoiceDate': 'max'}).reset_index()



HTML(df_customer.head().to_html())

Out[11]:

 CustomerIDInvoiceNoStockCodeAmountInvoiceDate
012346.0541431177183.602011-01-18 10:01:00
112346.0C5414331-77183.602011-01-18 10:17:00
212347.053762631711.792010-12-07 14:57:00
312347.054223729475.392011-01-26 14:30:00
412347.054922224636.252011-04-07 10:43:00

Artık istediğimiz değerleri hesaplayabiliriz. Her müşteri ve alışveriş için oluşturduğumuz tabloyu müşteri bazında tekrar gruplayacağız. Yapmak istediğimiz işlemler aşağıdakilerdir:

  • İşlem sayısını bulmak: ‘InvoiceNo’ kolonundaki değerleri sayacağız. Değerler tekil olduğu için count fonksiyonunu kullanabiliriz.
  • Toplam ve ortalam işlem miktarını bulmak: ‘Amount’ kolonu için toplam ve ortalama (mean) değerleri bulacağız.
  • En son alışveriş tarihini bulmak: Her müşteri için ‘InvoiceDate’ kolonundaki maksimum değeri bulacağız.

Miktar kolonunda yapacağımız iki işlem (toplam ve ortalama) için de dictionary yapısını ya da bir liste kullanabiliriz.

In [12]:

1
2
3
4
5
6
7
8
9
df_customer = df_customer.groupby('CustomerID').agg({'InvoiceNo':'count',
                                                     'Amount': ['sum','mean'],
                                                    'InvoiceDate': 'max'}).reset_index()



df_customer.columns = ['CustomerID', 'Number_of_Transactions', 'Total_Amount', 'Average_Amount', 'Last_Transaction_Date']

HTML(df_customer.head().to_html())

Out[12]:

 CustomerIDNumber_of_TransactionsTotal_AmountAverage_AmountLast_Transaction_Date
012346.020.000.0000002011-01-18 10:17:00
112347.074310.00615.7142862011-12-07 15:52:00
212348.041797.24449.3100002011-09-25 13:13:00
312349.011757.551757.5500002011-11-21 09:51:00
412350.01334.40334.4000002011-02-02 16:01:00

groupby()fonksiyonunu kullanarak veriyi özetledik. Bu noktadan sonra uygulamanıza göre veriden özetlediğiniz bilgileri kullanabilirsiniz.

Bu gönderi CC BY 4.0 lisansı altındadır.

Programlama ve algoritma ile problem çözme örnekleri

Pandas’a Giriş – Seriler