如何在熊猫中按两列计算唯一记录?

Posted

技术标签:

【中文标题】如何在熊猫中按两列计算唯一记录?【英文标题】:How to count unique records by two columns in pandas? 【发布时间】:2018-04-11 22:07:47 【问题描述】:

我在 pandas 中有数据框:

In [10]: df
Out[10]:
    col_a    col_b  col_c  col_d
0  France    Paris      3      4
1      UK    Londo      4      5
2      US  Chicago      5      6
3      UK  Bristol      3      3
4      US    Paris      8      9
5      US   London     44      4
6      US  Chicago     12      4

我需要计算独特的城市。我可以计算独特的状态

In [11]: df['col_a'].nunique()
Out[11]: 3

我可以尝试计算独特的城市

In [12]: df['col_b'].nunique()
Out[12]: 5

但这是错误的,因为美国的巴黎和法国的巴黎是不同的城市。所以现在我这样做:

In [13]: df['col_a_b'] = df['col_a'] + ' - ' + df['col_b']

In [14]: df
Out[14]:
    col_a    col_b  col_c  col_d         col_a_b
0  France    Paris      3      4  France - Paris
1      UK    Londo      4      5      UK - Londo
2      US  Chicago      5      6    US - Chicago
3      UK  Bristol      3      3    UK - Bristol
4      US    Paris      8      9      US - Paris
5      US   London     44      4     US - London
6      US  Chicago     12      4    US - Chicago

In [15]: df['col_a_b'].nunique()
Out[15]: 6

也许有更好的方法?无需创建额外的列。

【问题讨论】:

【参考方案1】:
import pandas as pd
data = 'field1':[1,4,1,68,9],'field2':[1,1,4,5,9]
df = pd.DataFrame(data)
results = df.groupby('field1')['field2'].nunique()
results

输出:

field1
1     2
4     1
9     1
68    1
Name: field2, dtype: int64

【讨论】:

【参考方案2】:

试试这个,我基本上是从 df 中的行数中减去重复组的数量。这是假设我们正在对 df 中的所有类别进行分组

df.shape[0] - df[['col_a','col_b']].duplicated().sum()

774 µs ± 603 ns per loop (mean ± std. dev. of 7 runs, 1000 loops each)

【讨论】:

【参考方案3】:

您可以选择col_acol_b,删除重复项,然后检查结果数据框的shape/len

df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 6

len(df[['col_a', 'col_b']].drop_duplicates())
# 6

因为groupby 会忽略NaNs,并且可能会不必要地调用排序过程,如果您在列中有NaNs,请相应地选择要使用的方法:

考虑如下数据框:

df = pd.DataFrame(
    'col_a': [1,2,2,pd.np.nan,1,4],
    'col_b': [2,2,3,pd.np.nan,2,pd.np.nan]
)

print(df)

#   col_a  col_b
#0    1.0    2.0
#1    2.0    2.0
#2    2.0    3.0
#3    NaN    NaN
#4    1.0    2.0
#5    4.0    NaN

时间

df = pd.concat([df] * 1000)

%timeit df.groupby(['col_a', 'col_b']).ngroups
# 1000 loops, best of 3: 625 µs per loop

%timeit len(df[['col_a', 'col_b']].drop_duplicates())
# 1000 loops, best of 3: 1.02 ms per loop

%timeit df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 1000 loops, best of 3: 1.01 ms per loop    

%timeit len(set(zip(df['col_a'],df['col_b'])))
# 10 loops, best of 3: 56 ms per loop

%timeit len(df.groupby(['col_a', 'col_b']))
# 1 loop, best of 3: 260 ms per loop

结果

df.groupby(['col_a', 'col_b']).ngroups
# 3

len(df[['col_a', 'col_b']].drop_duplicates())
# 5

df[['col_a', 'col_b']].drop_duplicates().shape[0]
# 5

len(set(zip(df['col_a'],df['col_b'])))
# 2003

len(df.groupby(['col_a', 'col_b']))
# 2003

所以区别:

选项1:

df.groupby(['col_a', 'col_b']).ngroups

速度很快,它会排除包含NaNs 的行。

选项 2 和 3:

len(df[['col_a', 'col_b']].drop_duplicates())
df[['col_a', 'col_b']].drop_duplicates().shape[0]

相当快,它将NaNs 视为唯一值。

选项 4 和 5:

len(set(zip(df['col_a'],df['col_b']))) 
len(df.groupby(['col_a', 'col_b'])) 

慢,是遵循numpy.nan == numpy.nan为False的逻辑,所以不同的(nan, nan)行被认为是不同的。

【讨论】:

【参考方案4】:

通过使用ngroups

df.groupby(['col_a', 'col_b']).ngroups
Out[101]: 6

或使用set

len(set(zip(df['col_a'],df['col_b'])))
Out[106]: 6

【讨论】:

【参考方案5】:
In [105]: len(df.groupby(['col_a', 'col_b']))
Out[105]: 6

【讨论】:

以上是关于如何在熊猫中按两列计算唯一记录?的主要内容,如果未能解决你的问题,请参考以下文章

如何在R中按两列分组

如何在c#中按两列对DataTable进行排序

将熊猫数据框按两列分组而不汇总

如何按对象计算熊猫组列中的不同值?

在熊猫中按组顺序计算差异

格式化按两列分组的熊猫数据系列,并在第三个重新采样,平均值为 dict