python pandas groupby优化

时间:2014-10-16 15:52:13

标签: python pandas group-by

我有一个包含许多行和列的大型数据框,我需要将其中一个列'group'分组 这是一个小例子

  group      rank             word
0     a  0.739631           entity
1     a  0.882556  physical_entity
2     b  0.588045      abstraction
3     b  0.640933            thing
4     c  0.726738           object
5     c  0.669280            whole
6     d  0.006574         congener
7     d  0.308684     living_thing
8     d  0.638631         organism
9     d  0.464244          benthos

基本上,我将应用一系列函数来创建新列并在组之后转换现有列,例如:

我想要实现的功能之一是top_word,它为每个组选择排名最高的单词。所以它的输出将是一个unicode列:

group    top_word
a    physical_entity [0.88]
b    thing [0.64]
c    object [0.73]
d    organism [0.63]

目前,我正在使用这种可怕的方法:

def top_word(tab):
    first = tab.iloc[0]
    res = '{} [{:.2f}]'.format(first['word'], first['rank'])
    return [res]

def aggr(x, fns):
    d = {key: fn(x) for key, fn in fns.iteritems()}
    return pd.DataFrame(d)

fs = {'top_word': top_word}
T = T.sort('rank', ascending=False) #sort by rank then I only have to pick the first result in the aggfunc!
T = T.groupby('group', sort=False).apply(lambda x: aggr(x, fs))
T.index = T.index.droplevel(level=1)

给出(例如,由于随机数生成器导致的结果不同):

time taken: 0.0042  +- 0.0003 seconds
                 top_word
group                    
a           entity [0.07]
b      abstraction [0.84]
c           object [0.92]
d         congener [0.06]

我已经设计了这个方法,所以我可以随时应用我想要的任何功能。它需要保持这种灵活性,但它似乎太可怕了!有没有更有效的方法来做这样的事情?迭代群体+追加更好吗?

由于

1 个答案:

答案 0 :(得分:1)

我认为首先是groupby,然后是sort每个group,并使用.agg()保留第一个观察结果:

In [192]:

print df
  group      rank             word
0     a  0.739631           entity
1     a  0.882556  physical_entity
2     b  0.588045      abstraction
3     b  0.640933            thing
4     c  0.726738           object
5     c  0.669280            whole
6     d  0.006574         congener
7     d  0.308684     living_thing
8     d  0.638631         organism
9     d  0.464244          benthos
In [193]:

print df.groupby('group').agg(lambda x: sorted(x, reverse=True)[0])
           rank             word
group                           
a      0.882556  physical_entity
b      0.640933            thing
c      0.726738            whole
d      0.638631         organism
In [194]:

df_res = df.groupby('group').agg(lambda x: sorted(x, reverse=True)[0])
df_res.word+df_res['rank'].apply(lambda x: ' [%.2f]'%x)
Out[194]:
group
a        physical_entity [0.88]
b                  thing [0.64]
c                  whole [0.73]
d               organism [0.64]
dtype: object