计算Pandas groupby中的唯一索引值

时间:2016-02-03 13:45:54

标签: python pandas

在Pandas中,有一种非常简洁的方法可以按操作计算组内列中的不同值。例如

ex = pd.DataFrame([[1, 2, 3], [6, 7, 8], [1, 7, 9]], 
                  columns=["A", "B", "C"]).set_index(["A", "B"])
ex.groupby(level="A").C.nunique()

将返回

A
1    2
6    1
Name: C, dtype: int64

我还希望在按B分组时计算索引级A中的不同值。我找不到从B对象访问groupby级别的简洁方法。我能想到的最好的是:

ex.reset_index("B", drop=False).groupby(level="A").B.nunique()

正确返回:

A
1    2
6    1
Name: B, dtype: int64 

我有没有办法在groupby上执行此操作而不重置索引或使用apply函数?

3 个答案:

答案 0 :(得分:4)

IIUC您可以为所有级别reset_index执行,然后将groupby设为'A'并应用nunique方法:

res = ex.reset_index().groupby('A').agg(lambda x: x.nunique())

In [339]: res
Out[339]:
   B  C
A
1  2  2
6  1  1

pivot_table相同的解决方案:

In [341]: ex.reset_index().pivot_table(index='A', aggfunc=lambda x: x.nunique())
Out[341]:
   B  C
A
1  2  2
6  1  1

答案 1 :(得分:1)

不确定这是否更好,但它不使用应用或重置索引:)

In [20]: ex.groupby(level="A").agg(lambda x: x.index.get_level_values(1).nunique())
Out[20]:
   C
A
1  2
6  1

FWIW,我发现在开发一个复杂的群体时打破这些是有用的。您可以通过

查看您将使用的各个对象
In [24]: ex.groupby(level="A").get_group(1)
Out[24]:
     C
A B
1 2  3
  7  9

合:

In [33]: (ex.groupby(level='A')
   ....:    .C.agg({'a': lambda x: x.index.get_level_values(1).nunique(),
   ....:            'b': 'nunique'}))
Out[33]:
   b  a
A
1  2  2
6  1  1

答案 2 :(得分:0)

为了您的娱乐,使用reset_indexapplyagg或匿名功能的不那么容易读出的解决方案。但是,它确实使用了标准库中的zipCounter

import pandas as pd
from collections import Counter

ex = pd.DataFrame([[1, 2, 3], [6, 7, 8], [1, 7, 9]], 
                  columns=["A", "B", "C"]).set_index(["A", "B"])

A_val, nunique_B = zip(*[(k, len(Counter(v.index.labels[v.index.names.index('B')]))) 
                      for k, v in ex.groupby(level='A')])

pd.Series(nunique_B, index=pd.Int64Index(A_val, name='A'))

返回

A
1    2
6    1
dtype: int32

另外,为了一般性,我不认为B处于索引的第1级。