pandas中的groupby()和索引值

4

我有一个带Multiindexpandas.DataFrame,如下所示:

a         val
   dog    1
   cat    2
b         
   fox    3
   rat    4

我希望有一个系列,其中每个条目都是一级索引值的列表,因此:
a    [dog, cat]
b    [fox, rat]

以下的方法可以实现,但是效率低且不够优雅:
fff = df.groupby(level=0)['val'].agg(lambda x:[i[1] for i in list(x.index.values)])

所以我希望有更好的方法。
2个回答

2

reset_index and groupby

df.reset_index(level=1).groupby(level=0)['level_1'].apply(list)


Out[21]: 
a    [dog, cat]
b    [fox, rat]
Name: level_1, dtype: object

谢谢!我不确定这是否更优雅,但它比另一种方法快五倍。 - Igor Rivin
1
@IgorRivin 哦,不客气~ 祝你编码愉快。 - BENY

1

为了获得比Wen's Answer更高一个数量级的速度提升,我们可以使用本地迭代器,例如:

代码:

index_as_dict = {}
for k, v in index.ravel():
    index_as_dict.setdefault(k, []).append(v)
pd.Series(index_as_dict)

测试代码:

import pandas as pd

df = pd.read_fwf(StringIO(u"""
    level_0  level_1     val
    a        dog         1
    a        cat         2
    b        fox         3
    b        rat         4"""), header=1).set_index(['level_0', 'level_1'])
print(df)

def method1():
    return df.reset_index(level=1).groupby(level=0)['level_1'].apply(list)

def method2():
    index_as_dict = {}
    for k, v in df.index.ravel():
        index_as_dict.setdefault(k, []).append(v)
    return pd.Series(index_as_dict)

print(method1())
print(method2())

from timeit import timeit
print(timeit(method1, number=50))
print(timeit(method2, number=50))

结果:

                 val
level_0 level_1     
a       dog        1
        cat        2
b       fox        3
        rat        4
level_0
a    [dog, cat]
b    [fox, rat]
Name: level_1, dtype: object
a    [dog, cat]
b    [fox, rat]
dtype: object

0.0760027870983045
0.006749932432252637

非常酷,尽管有点令人惊讶,但与我对pandas实现的内部模型相冲突 :) - Igor Rivin
1
此外,有趣的是,对于我的(非常大的)框架来说,这比温的方法慢了一些(约50%)。 - Igor Rivin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接