मुख्य सामग्री पर जाएँ

Groupby, split-apply-combine और pandas

इस ट्यूटोरियल में, आप pandas के groupby ऑपरेशन का उपयोग करना सीखेंगे, जो प्रसिद्ध split-apply-combine रणनीति से प्रेरित है, Netflix मूवी डेटा पर।
· 8 मि॰ पढ़ें

AI के साथ खोजें

Netflix ने हाल ही में कुछ उपयोगकर्ता रेटिंग डेटा जारी किया है। मैं एक सीधा-सा प्रश्न पूछना चाहता था: क्या Netflix सब्सक्राइबर पुरानी फिल्मों को अधिक पसंद करते हैं या नई फिल्मों को?

सहज रूप से, आप डेटा सेट को समूहों में बाँटना चाहेंगे, हर वर्ष के लिए एक समूह, फिर कोई सार-परिमाण (summary statistic) जैसे औसत (mean) या माध्यिका (median) निकालना, और फिर देखना कि क्या यह परिमाण वर्षों के साथ बढ़ता है (इसके बाद आप एक सांख्यिकीय परीक्षण भी करना चाहेंगे)।

अच्छी बात यह है कि ऐसा करने और इस पर सोचने के लिए एक वैचारिक ढांचा मौजूद है, और इसके Python तथा R दोनों में कार्यान्वयन हैं। इस ढांचे को "split-apply-combine" कहा जाता है क्योंकि हम...

  • चरण 1: मूल DataFrame से एक groupby ऑब्जेक्ट बनाकर डेटा को समूहों में बाँटते हैं;
  • चरण 2: एक फ़ंक्शन लगाते हैं, यहाँ एक समेकन (aggregation) फ़ंक्शन जो सार-परिमाण निकालता है (आप इस चरण में अपने डेटा को रूपांतरित या फ़िल्टर भी कर सकते हैं);
  • चरण 3: परिणामों को एक नए DataFrame में मिलाते हैं।

यह हमारे सामने विश्लेषण के लिए वैचारिक ढांचा है। इस पोस्ट में आप सीखेंगे कि ऊपर वाले Netflix रेटिंग प्रश्न का उत्तर Python पैकेज pandas का उपयोग करके कैसे दिया जाए। आप R में भी यही काम, उदाहरण के लिए, dplyr पैकेज से कर सकते हैं। मैं groupby ऑब्जेक्ट्स पर भी थोड़ा विस्तार से बात करूँगा, जो बहुत सहज नहीं होते। groupby ऑब्जेक्ट्स के साथ split-apply-combine की प्रक्रिया एक पैटर्न है जिसे हम सभी सहज रूप से करते हैं, जैसा कि हम देखेंगे, पर 2011 में Hadley Wickham ने अपने पेपर The Split-Apply-Combine Strategy for Data Analysis से इस प्रक्रिया को औपचारिक रूप दिया।

यदि आपको यह तकनीक उपयोगी लगे, तो आप इसके बारे में (और कई अन्य चीज़ों के बारे में) और सीख सकते हैं तथा अभ्यास कर सकते हैं हमारे Manipulating DataFrames with pandas कोर्स में।

pandas के साथ डेटा अन्वेषण

अपना डेटा आयात करें

यहाँ आप pandas, groupby ऑब्जेक्ट्स और split-apply-combine के सिद्धांतों का उपयोग करेंगे ताकि यह देख सकें कि रिलीज़ वर्ष के अनुसार Netflix फ़िल्मों की श्रेणियाँ कैसे बदलती हैं। मुझे यह डेटा मूल रूप से data.world पर यहाँ मिला। यदि आप इसे पुनरुत्पादित करना चाहें, तो इस पोस्ट का सारा कोड आपको यहाँ मिल जाएगा।

सबसे पहले आप आवश्यक पैकेज और डेटा आयात करेंगे और डेटा की पहले पाँच पंक्तियाँ देखेंगे:

# 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

यह मुझे काफ़ी अच्छा लग रहा है: आपके पास शीर्षक, रेटिंग, रिलीज़ वर्ष और उपयोगकर्ता रेटिंग स्कोर सहित कई अन्य कॉलम हैं। अपने groupby और split-apply-combine प्रक्रिया से पहले, डेटा को थोड़ा और करीब से देखते हैं ताकि यह सुनिश्चित हो कि यह वही है जो हम समझ रहे हैं और ताकि मिसिंग वैल्यूज़ को संभाला जा सके। ध्यान दें कि दूसरी पंक्ति (पंक्ति 1) के user_rating_score में एक मिसिंग वैल्यू NaN है।

प्लॉट्स और सांख्यिकी के साथ डेटा का सार-संक्षेप

pandas DataFrame की .info() विधि अमूल्य है। इसे नीचे लागू करने पर पता चलता है कि आपके पास 1000 पंक्तियाँ और 7 कॉलम हैं, साथ ही यह भी कि रुचि वाला कॉलम user_rating_score में केवल 605 non-null मान हैं। इसका अर्थ है कि 395 मान गायब हैं:

# 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

आप उन पंक्तियों को हटा सकते हैं जिनमें कोई भी मिसिंग वैल्यू है, किसी भी डुप्लिकेट पंक्ति को हटा सकते हैं और seaborn का उपयोग करके DataFrame का एक pairplot बना सकते हैं ताकि डेटा का विज़ुअल बोध हो सके। आप डेटा को 'rating' कॉलम के आधार पर रंग देंगे। प्लॉट्स देखें और देखें कि उनसे आपको क्या जानकारी मिलती है।

# 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

उदाहरण के लिए, user_rating_score को release_year के फ़ंक्शन के रूप में देखें। यहाँ कोई दृष्टिगत रूप से पहचानने योग्य प्रवृत्ति नज़र नहीं आती, लेकिन शायद कुछ डेटा विश्लेषण से कोई ट्रेंड सामने आए। यदि आप DataFrame की कई सार-सांख्यिकियाँ देखना चाहें, तो .describe() विधि से ऐसा कर सकते हैं:

# 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

प्रश्न का उत्तर देने के लिए groupby और split-apply-combine

चरण 1. Split

अब जब आपने डेटा देख लिया है, तो मज़ेदार हिस्सा शुरू करते हैं। आप पहले groupby विधि का उपयोग करके डेटा को समूहों में बाँटेंगे, जहाँ हर समूह किसी दिए गए वर्ष में रिलीज़ हुई फ़िल्मों का सेट होगा। यही split-apply-combine में split है:

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

यह एक groupby ऑब्जेक्ट बनाता है:

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

चरण 2. Apply

ऐसे groupby ऑब्जेक्ट्स बहुत उपयोगी होते हैं। याद करें कि DataFrame की .describe() विधि संख्यात्मक कॉलम्स के लिए सार-सांख्यिकियाँ लौटाती है? तो DataFrameGroupBy ऑब्जेक्ट्स की .describe() विधि भी हर संख्यात्मक कॉलम के लिए सार-सांख्यिकियाँ लौटाती है, लेकिन हर समूह पर अलग-अलग गणना करके। आपके मामले में, यह हर release_year के लिए है। यह split-apply-combine में apply का एक उदाहरण है: आप groupby के हर समूह पर .describe() विधि लगा रहे हैं। ऐसा करें और परिणाम की पहली 5 पंक्तियाँ प्रिंट करें:

# 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 rows × 24 columns

यदि आप देखना चाहें कि ग्रुपिंग कैसी दिखती है, तो आप groupby ऑब्जेक्ट को list() फ़ंक्शन में पास कर सकते हैं:

# 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  )

चरण 3. Combine

मान लीजिए कि आप हर वर्ष के लिए user_rating_score का औसत या माध्यिका चाहते हैं। तब आप क्रमशः .mean() या .median() विधि को groupby ऑब्जेक्ट पर लगा सकते हैं और इन्हें एक नए DataFrame में 'मिला' सकते हैं।

# 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

यहाँ DataFrame df_med_by_year के इंडेक्स से जुड़ा एक महत्वपूर्ण सूक्ष्म बिंदु है। याद करें कि किसी DataFrame का इंडेक्स पंक्ति लेबल्स से बना होता है। मूल DataFrame df का इंडेक्स देखें:

# 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)

यह इंडेक्स मूल पंक्ति संख्याओं से बना है, जो पूर्णांकों से चिह्नित हैं। ऊपर आपने कुछ पंक्तियाँ हटाई थीं, इसलिए '1' गायब है। df_med_by_year का इंडेक्स उस मूल कॉलम के मानों से बना है जिसके आधार पर आपने ग्रुपिंग की, यानी release_year के वर्ष:

# 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')

आपको user_rating_score कॉलम में रुचि है, जिसमें हर वर्ष के लिए माध्यिका रेटिंग है। आप df_med_by_year के user_rating_score कॉलम को स्लाइस कर सकते हैं और वर्ष के फ़ंक्शन के रूप में (जो DataFrame df_rat_by_year के इंडेक्स से दिया गया है) प्लॉट कर सकते हैं:

# 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

चित्र को देखते हुए, माध्यिका रेटिंग समय के साथ निश्चित रूप से बढ़ती दिखती है। समग्र प्रवृत्ति के बारे में मुझे आश्वस्त करने के लिए आपको कुछ और उन्नत सांख्यिकी का सहारा लेना होगा, लेकिन यह एक उदाहरण है कि किस तरह अन्वेषणात्मक डेटा विश्लेषण आगे के शोध के लिए एक अच्छा प्रारंभिक बिंदु होता है।

दैनिक उपयोग में groupby और split-apply-combine

Groupby ऑब्जेक्ट्स सहज नहीं होते। फिर भी, वे डेटा सेट को उसकी किसी एक कॉलम (या एक से अधिक, पर इसे हम किसी और पोस्ट के लिए रखते हैं जहाँ हम बहु-कॉलम ग्रुपिंग और पदानुक्रमित इंडेक्स की बात करेंगे) के सापेक्ष बाँटने की एक स्वाभाविक क्रिया से मेल खाते हैं।

split-apply-combine का सिद्धांत न केवल सुंदर और व्यावहारिक है, बल्कि यह ऐसी चीज़ है जिसका डेटा साइंटिस्ट रोज़ उपयोग करते हैं, जैसा कि ऊपर के उदाहरण में है। इसके उपयोगों की और सराहना करने के लिए, Hadley Wickham का मूल पेपर The Split-Apply-Combine Strategy for Data Analysis देखें। यदि आपके कोई विचार, प्रतिक्रियाएँ और/या मनन हों, तो ट्विटर पर मुझसे बेझिझक संपर्क करें: @hugobowne।

DataCamp के अन्य उपयोगी pandas ट्यूटोरियल भी देखें, जिनमें शामिल हैं:

विषय