यहाँ दो शीर्ष उत्तर सुझाते हैं:
df.groupby(cols).agg(lambda x:x.value_counts().index[0])
या, अधिमानतः
df.groupby(cols).agg(pd.Series.mode)
हालाँकि, ये दोनों साधारण किनारे के मामलों में विफल हैं, जैसा कि यहाँ दिखाया गया है:
df = pd.DataFrame({
'client_id':['A', 'A', 'A', 'A', 'B', 'B', 'B', 'C'],
'date':['2019-01-01', '2019-01-01', '2019-01-01', '2019-01-01', '2019-01-01', '2019-01-01', '2019-01-01', '2019-01-01'],
'location':['NY', 'NY', 'LA', 'LA', 'DC', 'DC', 'LA', np.NaN]
})
सबसे पहला:
df.groupby(['client_id', 'date']).agg(lambda x:x.value_counts().index[0])
पैदावार IndexError
(समूह द्वारा लौटाई गई खाली श्रृंखला के कारण C
)। द्वितीय:
df.groupby(['client_id', 'date']).agg(pd.Series.mode)
रिटर्न ValueError: Function does not reduce
, चूंकि पहला समूह दो की सूची देता है (क्योंकि दो मोड हैं)। (जैसा कि यहां दस्तावेज किया गया है , अगर पहले समूह ने एक भी मोड लौटाया तो यह काम करेगा!)
इस मामले के दो संभावित समाधान हैं:
import scipy
x.groupby(['client_id', 'date']).agg(lambda x: scipy.stats.mode(x)[0])
और CS95 द्वारा मुझे दिए गए समाधान यहाँ टिप्पणियों में दिए गए हैं :
def foo(x):
m = pd.Series.mode(x);
return m.values[0] if not m.empty else np.nan
df.groupby(['client_id', 'date']).agg(foo)
हालांकि, ये सभी धीमे हैं और बड़े डेटासेट के लिए अनुकूल नहीं हैं। एक समाधान जिसका मैंने उपयोग किया था, a) इन मामलों से निपट सकता है और b) बहुत, बहुत तेज है, abw33 के उत्तर का हल्का संशोधित संस्करण है (जो अधिक होना चाहिए):
def get_mode_per_column(dataframe, group_cols, col):
return (dataframe.fillna(-1)
.groupby(group_cols + [col])
.size()
.to_frame('count')
.reset_index()
.sort_values('count', ascending=False)
.drop_duplicates(subset=group_cols)
.drop(columns=['count'])
.sort_values(group_cols)
.replace(-1, np.NaN))
group_cols = ['client_id', 'date']
non_grp_cols = list(set(df).difference(group_cols))
output_df = get_mode_per_column(df, group_cols, non_grp_cols[0]).set_index(group_cols)
for col in non_grp_cols[1:]:
output_df[col] = get_mode_per_column(df, group_cols, col)[col].values
अनिवार्य रूप से, विधि एक समय में एक कर्नल पर काम करती है और एक df को आउटपुट करती है, इसलिए इसके बजाय concat
, जो गहन है, आप पहले को df मानते हैं, और फिर values.flatten()
df में स्तंभ के रूप में iteratively आउटपुट सरणी ( ) जोड़ते हैं ।