2016-11-24 38 views
1

我有熊猫数据框,看起来像这样:数据框列排序基于最常见的字符串

Name Hobby 
Andrew Football 
Kevin Photo 
Andrew Football 
Kevin Games 
Andrew Travel 
Kevin Games 

期望的结果将是安德鲁:足球;凯文:游戏。这可能是一个字典或数据库。我不能仅仅为一个名字排序,然后做Hobbies的idxmax,因为我的名字列可以用更多或更少的名字更新。我想:

sorted = sorted.drop_duplicates() 
sorted1 = {k: g["Hobby"].tolist() for k,g in sorted.groupby("Names")} 

但是这会带来所有的爱好,而不是只有最经常性的。

回答

2

下面是一个将返回名称和最常见的业余爱好收录了一系列相关的解决方案:

df.groupby('Name')['Hobby'].agg(lambda x: pd.value_counts(x).index[0]) 

Name 
Andrew Football 
Kevin  Games 
Name: Hobby, dtype: object 
1

您可以使用双groupby更快的解决方案与sizenlargest

df3 = df.groupby(['Names', 'Hobby']) 
     .size() 
     .groupby(level=0) 
     .nlargest(1) 
     .reset_index(level=0, drop=True) 
     .reset_index(name='Count') 

另一种解决方案是使用Counter

from collections import Counter 

df1 = df.groupby('Names')['Hobby'].apply(lambda x: Counter(x).most_common(1)[0][0]) 

时序

In [52]: %timeit df.groupby(['Names', 'Hobby']).size().groupby(level=0).nlargest(1).reset_index(level=0, drop=True).reset_index(name='Count') 
1 loop, best of 3: 191 ms per loop 

In [53]: %timeit df.groupby('Names')['Hobby'].apply(lambda x: Counter(x).most_common(1)[0][0]) 
1 loop, best of 3: 242 ms per loop 

In [54]: %timeit df.groupby('Names')['Hobby'].agg(lambda x: pd.value_counts(x).index[0]) 
1 loop, best of 3: 345 ms per loop 

代码进行测试

#[1000000 rows x 2 columns] 
np.random.seed(123) 
N = 1000000 
L1 = ['Andrew', 'Kevin','Joe','John', 'Bob', 'Peter'] 
L2 = ['Football','Photo','Games','Travel'] 
df = pd.DataFrame({'Names':np.random.choice(L1, N), 
        'Hobby': np.random.choice(L1, N)}) 

print (df)