使用Pandas按组将零值替换为组内非零值的技术需求
问题:分组替换零值为组内唯一非零值
需要在大型Pandas DataFrame中,将每个分组内的所有零值替换为该组内唯一的非零值。示例场景为:每天仅有一个小时的value字段为非零值,其余小时均为零值。
示例数据
创建示例DataFrame的代码
import pandas as pd data = { 'week': [1,1,1,1,1,1,1,1,1], 'day': [1,1,1,2,2,2,3,3,3], 'hour': [1,2,3,1,2,3,1,2,3], 'value': [0,123,0,456,0,0,0,789,0] } simple = pd.DataFrame(data)
原始DataFrame内容
| week | day | hour | value |
|---|---|---|---|
| 1 | 1 | 1 | 0 |
| 1 | 1 | 2 | 123 |
| 1 | 1 | 3 | 0 |
| 1 | 2 | 1 | 456 |
| 1 | 2 | 2 | 0 |
| 1 | 2 | 3 | 0 |
| 1 | 3 | 1 | 0 |
| 1 | 3 | 2 | 789 |
| 1 | 3 | 3 | 0 |
期望处理结果
将每天(按week+day分组)内的零值替换为当天的非零值,处理后结果如下(可选择替换原列或新增列):
| week | day | hour | value |
|---|---|---|---|
| 1 | 1 | 1 | 123 |
| 1 | 1 | 2 | 123 |
| 1 | 1 | 3 | 123 |
| 1 | 2 | 1 | 456 |
| 1 | 2 | 2 | 456 |
| 1 | 2 | 3 | 456 |
| 1 | 3 | 1 | 789 |
| 1 | 3 | 2 | 789 |
| 1 | 3 | 3 | 789 |
解决方案
针对大型DataFrame,推荐使用向量化分组操作,避免循环提升效率:
方法1:使用groupby.transform提取组内非零值
# 方式1:新增填充后的列 simple['filled_value'] = simple.groupby(['week', 'day'])['value'].transform( lambda x: x[x != 0].iloc[0] ) # 方式2:直接替换原列 simple['value'] = simple.groupby(['week', 'day'])['value'].transform( lambda x: x[x != 0].iloc[0] )
原理:按week和day分组后,transform会对每个组执行lambda函数——筛选出非零值(每个组仅一个)并取第一个值,最终返回与原数据索引对齐的结果,自动完成零值替换。
方法2:结合mask与groupby.transform
由于每个组仅存在一个非零值,使用max/min/sum均可直接获取该值,代码更简洁:
simple['value'] = simple['value'].mask( simple['value'] == 0, simple.groupby(['week', 'day'])['value'].transform('max') )
原理:mask会将value为0的位置替换为后面的对应值,而groupby.transform('max')会返回每个组的非零值,与原数据索引对齐。
内容的提问来源于stack exchange,提问作者twin_pilgrim
相关产品推荐
相关产品推荐

