Ana içeriğe geç

Groupby, böl-uygula-birleştir ve pandas

Bu eğitimde, Netflix film verileri üzerinde, iyi bilinen böl-uygula-birleştir stratejisinden yararlanan pandas groupby işlemini nasıl kullanacağınızı öğreneceksiniz.
· 8 dk. oku

Yapay Zeka ile Keşfedin

Netflix yakın zamanda bazı kullanıcı derecelendirme verilerini yayımladı. Ben de basit bir soru sormak istedim: Netflix aboneleri daha eski filmleri mi, yoksa daha yeni filmleri mi tercih ediyor?

Sezgisel olarak, veri kümesini yıllara göre gruplara ayırmak, ardından ortalama veya medyan gibi bir özet istatistik hesaplamak ve bu istatistiğin yıllar içinde artıp artmadığını görmek istersiniz (bundan sonra istatistiksel bir test de yapmak isteyebilirsiniz).

Güzel olan şu ki, bunu yapmak ve bu şekilde düşünmek için hem Python hem de R’de uygulanmış kavramsal bir çerçeve var. Bu çerçeve, "böl-uygula-birleştir" olarak bilinir; çünkü...

  • Adım 1: veriyi, orijinal DataFrame’den bir groupby nesnesi oluşturarak gruplara bölersiniz;
  • Adım 2: bu örnekte bir özet istatistik hesaplayan bir toplulaştırma fonksiyonunu uygularsınız (bu adımda verinizi dönüştürebilir veya filtreleyebilirsiniz de);
  • Adım 3: sonuçları yeni bir DataFrame’de birleştirirsiniz.

Bu, elimizdeki analizin kavramsal çerçevesi. Bu yazıda, Python paketi pandas’ı kullanarak yukarıdaki Netflix derecelendirme sorusunu nasıl yanıtlayacağınızı öğreneceksiniz. Aynısını R’de örneğin dplyr paketiyle de yapabilirsiniz. Ayrıca, çok da sezgisel olmayan groupby nesnelerine de değineceğim. Groupby nesneleriyle böl-uygula-birleştir süreci, aslında hepimizin sezgisel olarak yaptığı bir kalıp; ancak bu prosedürü 2011’de Hadley Wickham, Veri Analizi için Böl-Uygula-Birleştir Stratejisi başlıklı makalesiyle resmileştirdi.

Bu tekniği faydalı bulursanız, (ve daha pek çok şeyi) pandas ile DataFrame’leri Manipüle Etme kursumuzda öğrenebilir ve pratik edebilirsiniz.

pandas ile Veri Keşfi

Verinizi içe aktarın

Burada, pandas, groupby nesneleri ve böl-uygula-birleştir ilkelerini kullanarak Netflix film derecelendirmelerinin, filmlerin vizyon yılına göre nasıl değiştiğine bakacaksınız. Veriye ilk olarak data.world’de burada rastladım. Tüm kodu çoğaltmak isterseniz bu yazının kodlarını burada bulabilirsiniz.

Önce gerekli paketleri ve veriyi içe aktaracak ve verinin ilk beş satırına bakacaksınız:

# Import packages and set visualization style
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
%matplotlib inline
# Import data and check out head of DataFrame
df = pd.read_csv('data/chasewillden-netflix-shows/data/netflix.csv')
df.head()
 titleratingratinglevelratingdescriptionrelease_yearuser_rating_scoreuser_rating_size
0White ChicksPG-13crude and sexual humor, language and some drug...80200482.080
1Lucky Number SlevinRstrong violence, sexual content and adult lang...1002006NaN82
2Grey's AnatomyTV-14Parents strongly cautioned. May be unsuitable ...90201698.080
3Prison BreakTV-14Parents strongly cautioned. May be unsuitable ...90200898.080
4How I Met Your MotherTV-PGParental guidance suggested. May not be suitab...70201494.080

Bu bana oldukça iyi görünüyor: başlıklar, derecelendirmeler, vizyon yılı ve kullanıcı puanı gibi birçok sütun var. Groupby ve böl-uygula-birleştir prosedürümüzü uygulamadan önce, verinin gerçekten beklediğimiz gibi olduğundan emin olmak ve eksik değerlerle ilgilenmek için biraz daha yakından bakalım. İkinci satırda (satır 1) user_rating_score sütununda NaN şeklinde bir eksik değer olduğunu unutmayın.

Verinizi grafikler ve istatistiklerle özetleme

pandas DataFrame’in .info() metodu çok değerlidir. Aşağıda uyguladığınızda, 1000 satır ve 7 sütun veriniz olduğunu; ancak ilgi alanımız olan user_rating_score sütununda sadece 605 adet null olmayan değer bulunduğunu gösterir. Bu da 395 eksik değer olduğu anlamına gelir:

# Check out info of DataFrame
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1000 entries, 0 to 999
Data columns (total 7 columns):
title                1000 non-null object
rating               1000 non-null object
ratinglevel          941 non-null object
ratingdescription    1000 non-null int64
release_year         1000 non-null int64
user_rating_score    605 non-null float64
user_rating_size     1000 non-null int64
dtypes: float64(1), int64(3), object(3)
memory usage: 54.8+ KB

Herhangi bir eksik değeri olan satırları düşürebilir, yinelenen satırları kaldırabilir ve veriye görsel bir bakış atmak için seaborn kullanarak DataFrame’in bir pairplot grafiğini oluşturabilirsiniz. Veriyi 'rating' sütununa göre renklendireceksiniz. Grafikleri inceleyin ve hangi bilgileri çıkarabildiğinize bakın.

# Drop rows with missing values and drop duplicate
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)

# Visualize pairplot of df
sns.pairplot(df, hue='rating');

pairplot seaborn

Örneğin, user_rating_score’u release_year’ın bir fonksiyonu olarak inceleyin. Görsel olarak belirgin bir eğilim yok ama belki biraz veri analizi bir eğilimi ortaya çıkarır. DataFrame’in birkaç özet istatistiğine de bakmak isterseniz .describe() metodunu kullanabilirsiniz:

# Get summary stats of df
df.describe()
 ratingdescriptionrelease_yearuser_rating_scoreuser_rating_size
count246.000000246.000000246.000000246.0
mean73.5569112010.27235881.39024480.0
std26.6161458.88721912.6778830.0
min10.0000001940.00000055.00000080.0
25%60.0000002007.00000071.00000080.0
50%80.0000002015.00000083.50000080.0
75%90.0000002016.00000092.75000080.0
max124.0000002017.00000099.00000080.0

Soruyu yanıtlamak için groupby ve böl-uygula-birleştir

Adım 1. Böl

Artık veriyi incelediğinize göre, işin eğlenceli kısmına geçebiliriz. Önce veriyi bir groupby yöntemiyle gruplara böleceksiniz; burada her grup belirli bir yılda vizyona giren filmlerden oluşacak. Bu, böl-uygula-birleştir içindeki böl adımıdır:

# Group by year
df_by_year = df.groupby('release_year')

Bu bir groupby nesnesi oluşturur:

# Check type of GroupBy object
type(df_by_year)
pandas.core.groupby.DataFrameGroupBy

Adım 2. Uygula

Bu tür groupby nesneleri çok kullanışlıdır. DataFrame için .describe() metodunun sayısal sütunlar için özet istatistikler döndürdüğünü hatırlayın. DataFrameGroupBy nesneleri için .describe() metodu da her sayısal sütun için özet istatistikler döndürür; ancak bunu bölünmüş her grup için ayrı ayrı hesaplar. Sizin durumunuzda bu, her release_year için geçerlidir. Bu, böl-uygula-birleştir içindeki uygula adımına bir örnektir: groupby içindeki her gruba .describe() metodunu uyguluyorsunuz. Bunu yapın ve sonucun ilk 5 satırını yazdırın:

# Summary stats over years
df_by_year.describe().head()
 ratingdescriptionuser_rating_scoreuser_rating_size
 countmeanstdmin25%50%75%maxcountmean...75%maxcountmeanstdmin25%50%75%max
release_year                     
19401.035.0NaN35.035.035.035.035.01.061.0...61.061.01.080.0NaN80.080.080.080.080.0
19781.060.0NaN60.060.060.060.060.01.086.0...86.086.01.080.0NaN80.080.080.080.080.0
19821.060.0NaN60.060.060.060.060.01.068.0...68.068.01.080.0NaN80.080.080.080.080.0
19861.035.0NaN35.035.035.035.035.01.067.0...67.067.01.080.0NaN80.080.080.080.080.0
19871.060.0NaN60.060.060.060.060.01.058.0...58.058.01.080.0NaN80.080.080.080.080.0

5 satır × 24 sütun

Gruplamanın nasıl göründüğünü görmek isterseniz, groupby nesnesini list() fonksiyonuna gönderebilirsiniz:

# Cast grouping as a list and check out one year
list(df_by_year)[10]
(1995,             title rating                                ratinglevel  \
 766         Balto      G  General Audiences. Suitable for all ages.   
 967  Heavyweights     PG              some rude language and pranks   

      ratingdescription  release_year  user_rating_score  user_rating_size  
 766                 35          1995               64.0                80  
 967                 60          1995               74.0                80  )

Adım 3. Birleştir

Diyelim ki her yıl için ortalama ya da medyan user_rating_score değerini istiyorsunuz. O zaman groupby nesnesine sırasıyla .mean() veya .median() metodunu uygulayabilir ve bunları yeni bir DataFrame’de "birleştirebilirsiniz".

# Get median values by year and print first 5 rows
df_med_by_year = df_by_year.median()
df_med_by_year.head()
 ratingdescriptionuser_rating_scoreuser_rating_size
release_year   
194035.061.080.0
197860.086.080.0
198260.068.080.0
198635.067.080.0
198760.058.080.0

df_med_by_year DataFrame’inin indeksine dair önemli bir incelik var. Bir DataFrame’in indeksi, satır etiketlerinden oluşur. Orijinal DataFrame df’nin indeksine bakın:

# Print index of df
print(df.index)
Int64Index([  0,   2,   3,   4,   5,   6,   7,   8,   9,  10,
            ...
            908, 911, 917, 931, 962, 966, 967, 972, 973, 979],
           dtype='int64', length=246)

Bu indeks, orijinal satır numaralarından, yani tamsayılardan oluşur. Yukarıda bazı satırları düşürdüğünüz için '1' eksik. df_med_by_year’ın indeksi ise gruplama yaptığınız orijinal sütundaki değerlerden, yani release_year yıllarından oluşur:

# Print index
print(df_med_by_year.index)
Int64Index([1940, 1978, 1982, 1986, 1987, 1989, 1990, 1992, 1993, 1994, 1995,
            1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
            2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017],
           dtype='int64', name='release_year')

Her yıl için medyan puanı içeren user_rating_score sütunuyla ilgileniyorsunuz. df_med_by_year’ın user_rating_score sütununu dilimleyebilir ve bunu yılın (yani df_rat_by_year DataFrame’inin indeksi) bir fonksiyonu olarak çizebilirsiniz:

# Slice out user rating and plot
df_rat_by_year = df_med_by_year['user_rating_score']
plt.scatter(df_rat_by_year.index, df_rat_by_year)
plt.xlabel('year of release')
plt.ylabel('median rating');

Netflix groupby split-apply-combine

Şekle bakılırsa medyan puan zaman içinde kesinlikle artıyor. Genel bir eğilime beni ikna etmek için daha gelişmiş istatistiklerden yararlanmanız gerekir; ancak bu, Keşifsel Veri Analizi’nin ileri araştırmalar için harika bir başlangıç olduğuna güzel bir örnek.

Günlük kullanımlarda groupby ve böl-uygula-birleştir

Groupby nesneleri sezgisel değildir. Yine de bir veri kümesini, sütunlarından birine (veya birkaçına—ancak birden fazla sütuna göre gruplama ve hiyerarşik indeksler konusunu başka bir yazıya bırakalım) göre bölme eylemiyle doğal olarak örtüşürler.

Böl-uygula-birleştir ilkesi yalnızca zarif ve pratik olmakla kalmaz; tıpkı yukarıdaki örnekte olduğu gibi Veri Bilimcilerin her gün kullandığı bir yaklaşımdır. Daha fazla kullanım alanını görmek için Hadley Wickham’ın orijinal makalesine, Veri Analizi için Böl-Uygula-Birleştir Stratejisi’ne göz atın. Görüş, yorum ve/veya düşüncelerinizi paylaşmak isterseniz Twitter’da bana ulaşabilirsiniz: @hugobowne.

DataCamp’in diğer faydalı pandas eğitimlerine de göz atın:

Konular

İlgili