看过来
《pandas 教程》 持续更新中,提供建议、纠错、催更等加作者微信: gairuo123(备注:pandas教程)和关注公众号「盖若」ID: gairuo。跟作者学习,请进入 Python学习课程。欢迎关注作者出版的书籍:《深入浅出Pandas》 和 《Python之光》。
pandas 中的 Series 可以转为字典,Series 的 map() 也可以使用另外 Series 来做值的映射。在这个案例中,我们充分应用以上的特性来解决我们实际中遇到的问题。
数据集如下:
import pandas as pd
df1 = pd.DataFrame({'group': [*'abc'], 'amt': [1, 2, 0]})
df2 = pd.DataFrame({'group': [*'aabbcc'], 'price': range(10, 61, 10)})
df1
'''
group amt
0 a 1
1 b 2
2 c 0
'''
df2
'''
group price
0 a 10
1 a 20
2 b 30
3 b 40
4 c 50
5 c 60
'''
想要得到如下数据:
'''
group price flag
0 a 10 NaN
1 a 20 a20
2 b 30 b30
3 b 40 b40
4 c 50 NaN
5 c 60 NaN
'''
新增加了 flag 列,flag 由 group 和 price 组合而成。但是,部分行的值为空,部分有值,有值的是所在 group 分组内按 price 降序排列,并由 df1 的 amt 决定有值的数量。df1 中的 amt 为对应分组 group 的数量值。
思路为写一个函数,让按 group 分组后的分组对象来应用,这个函数传入的是各个子 DataFrame。
对子 DataFrame 的按 price 降序,并取前几个并拼接起来。前几个数量由 df1 中的数据来确定,可以先将 df1 转为一个字典,这个字典代码不同组要取的数量。最终得到一个 df2 数据索引对应的接续数据。
最后,根据 df2 的索引将上边的映射数据添加到新列中。
根据思路,先将 df1 的数据转为一个字典,待用。
group_map = df1.set_index('group').amt.to_dict()
group_map
# {'a': 1, 'b': 2, 'c': 0}
编写函数,top 为取此组取的数量。按 price 排序后,取前 top 个数量转为字符串类型,并用 sum() 拼接。
def func(d: pd.DataFrame):
top = group_map.get(d.name) # df1 中 group 的数量
foo = d.sort_values('price', ascending=False)
foo = foo.head(top).astype(str).sum(1)
return foo
按分组应用这个函数:
data_map = df2.groupby('group', group_keys=False).apply(func)
data_map
'''
1 a20
3 b40
2 b30
dtype: object
'''
将以上映射数据添加到新列:
df2.assign(flag=df2.index.map(data_map))
'''
group price flag
0 a 10 NaN
1 a 20 a20
2 b 30 b30
3 b 40 b40
4 c 50 NaN
5 c 60 NaN
'''
这样就得到了想要的结果。
(完)
更新时间:2024-08-18 16:01:42 标签:pandas python 分组 排序 拼接