根据另一列的分组计数添加pandas列?

时间:2015-01-07 11:55:18

标签: python pandas

如果我有一个包含以下内容的pandas数据框:

    Visited   PersonId
0   GB        1
1   US        1
2   US        1
3   GB        1
4   DE        1
5   CN        2
6   US        2
7   GB        3
8   GB        4

添加新列的最简单方法是什么?该列包含每个PersonId访问过的唯一国家/地区数量?

例如,对于上述情况,第1人访问了3个不同的国家。添加新列后的新数据框应如下所示:

    Visited   PersonId    CountryCount
0   GB        1           3
1   US        1           3
2   US        1           3
3   GB        1           3
4   DE        1           3
5   CN        2           2
6   US        2           2
7   GB        3           1
8   GB        4           1

3 个答案:

答案 0 :(得分:3)

这有效,但我觉得有更好的方法

In [104]:

df['CountryCount'] = df['PersonId'].map(df.groupby(['PersonId'])['Visited'].unique().apply(len))
df
Out[104]:
  Visited  PersonId  CountryCount
0      GB         1             3
1      US         1             3
2      US         1             3
3      GB         1             3
4      DE         1             3
5      CN         2             2
6      US         2             2
7      GB         3             1
8      GB         4             1

答案 1 :(得分:2)

不知道这是否更优雅,但这是有效的

>>> g = df.groupby('PersonId')['Visited'].nunique().reset_index()
>>> g.columns = ['PersonId', 'CountryCount']
>>> pd.merge(df, g)
  Visited  PersonId  CountryCount
0      GB         1             3
1      US         1             3
2      US         1             3
3      GB         1             3
4      DE         1             3
5      CN         2             2
6      US         2             2
7      GB         3             1
8      GB         4             1

或者,正如@EdChum在评论中建议的那样,它可以缩短为

df['CountryCount'] = df['PersonId'].map(df.groupby('PersonId')['Visited'].nunique())

为了以防万一,我已经检查了所有答案的执行时间。虽然在OP案例中我并不认为它真的很重要,但事实证明@EdChum方法在这里是明显的赢家:

In [7]: %timeit df["CountryCount"] = df.groupby("PersonId")["Visited"].transform(pd.Series.nunique)
100 loops, best of 3: 2.32 ms per loop

In [8]: %timeit df['CountryCount'] = df['PersonId'].map(df.groupby('PersonId')['Visited'].nunique())
100 loops, best of 3: 2.52 ms per loop

In [9]: %timeit df['CountryCount'] = df['PersonId'].map(df.groupby(['PersonId'])['Visited'].unique().apply(len))
1000 loops, best of 3: 1.29 ms per loop

经过额外测试后,我发现@DSM和@EdChums的组合工作得更快:)

In [26]: %timeit df["CountryCount"] = df.groupby("PersonId")["Visited"].transform(lambda x: x.unique().size)
1000 loops, best of 3: 952 µs per loop

Here's在github上以某种方式相关的问题。

答案 2 :(得分:2)

如果您想在群组中“广播”,通常会使用transform

>>> df["CountryCount"] = df.groupby("PersonId")["Visited"].transform(pd.Series.nunique)
>>> df
  Visited  PersonId CountryCount
0      GB         1            3
1      US         1            3
2      US         1            3
3      GB         1            3
4      DE         1            3
5      CN         2            2
6      US         2            2
7      GB         3            1
8      GB         4            1