Python 计算Pandas groupby中的唯一索引值

Python 计算Pandas groupby中的唯一索引值,python,pandas,Python,Pandas,在Pandas中,有一种非常干净的方法可以按操作对group中的列中的不同值进行计数。比如说 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 我还想计算

在Pandas中,有一种非常干净的方法可以按操作对group中的列中的不同值进行计数。比如说

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
分组。我找不到从
groupby
对象访问
B
级别的干净方法。我能想到的最好的办法是:

ex.reset_index("B", drop=False).groupby(level="A").B.nunique()
正确返回:

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

我是否有办法在groupby上执行此操作,而无需重置索引或使用
apply
功能?

IIUC您可以对所有级别执行
reset\u 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
与透视表相同的解决方案:

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

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

FWIW,我发现在开发一个复杂的groupby时,将它们分开是很有用的。您可以查看将使用的单个对象

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

为了您的娱乐,这是一个不太容易大声读出的解决方案,它不使用
reset\u index
、或
apply
、或
agg
、或匿名函数。但是,它确实使用标准库中的
zip
Counter

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级

A
1    2
6    1
dtype: int32