根据另一列的分组计数添加 pandas 列?
Adding a pandas column based on grouped counts of another column?
如果我有一个 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
这个可行,但我觉得还有更好的方法
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
不知道这是否可以更优雅,但这有效
>>> 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.
的某种相关问题
当您想 "broadcast" 跨组时,通常使用 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
如果我有一个 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
这个可行,但我觉得还有更好的方法
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
不知道这是否可以更优雅,但这有效
>>> 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.
当您想 "broadcast" 跨组时,通常使用 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