Python Pandas groupby 优化

0 投票
1 回答
597 浏览
提问于 2025-04-27 23:30

我有一个很大的数据表,里面有很多行和列,我需要根据其中一列'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 个回答

1

我觉得这个想法是先用 groupby 把数据分组,然后对每个 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

撰写回答