python - 用下一个和上一个正数的平均值替换负数、NaN 和 0
问题描述
我想用同一列的下一个和上一个正数的平均值替换负数、NaN 和 0。
原始数据框
a c
0 1 1
1 2 2
2 0 5
3 -3 NaN
4 -1 5
5 3 3
预期的输出数据帧是
a c
0 1 1
1 2 2
2 2.5 5 #In Col a --> Mean of 2 and 3 is 2.5 hence 0 replaced by 2.5
3 2.75 5 #In Col a --> Mean of 2.5 and 3 is 2.75 hence negative no. replaced by 2.75
4 2.875 5 #In Col a --> Mean of 2.75 and 3 is 2.875 hence negative no. replaced by 2.875
5 3 3
我尝试了另一种策略来处理否定的否。Nan 和 0 用前 3 个值的平均值替换它
m = df['a'] < 1
new = (df.loc[~m, 'a'].astype(float)
.rolling(2, min_periods=1).mean()
.reindex(df.index, method='ffill'))
df['a'].mask(m, new)
这导致
0 1.0
1 2.0
2 1.5
3 1.5
4 1.5
5 2.0
Name: a, dtype: float64
但是,我正在努力实施新战略(被问到)。
解决方案
我编辑了我的答案以更好地解决您的问题。但是请注意,5 和 5 的平均值是 5,而不是您在预期结果中写的 2.5。
这个新答案基于下面 hpchavaz 的答案。
# Replace 0 and negative values with NaN
df = df.mask(df<=0)
# Compute rank of consecutive NaN values
rank = df.isnull().astype('int')
rank = rank.cumsum() - rank.cumsum().where(rank==0).ffill().fillna(0)
print(rank)
a b
0 0.0 0.0
1 0.0 0.0
2 1.0 0.0
3 2.0 1.0
4 3.0 0.0
5 0.0 0.0
# Compute first and last non null value before NaN range
first = df.ffill()
last = df.bfill()
# Finally, compute final df
df = last - (last-first)/2**(rank)
print(df)
a b
0 1.000 1.0
1 2.000 2.0
2 2.500 5.0
3 2.750 5.0
4 2.875 5.0
5 3.000 3.0
上一个答案
您可以调用mask
用 NaN 替换空值和负值,然后interpolate
不太确定为什么您希望第二列中的 NaN 被替换为 2.5 而不是 5 ......
>>> df.mask(df<=0).interpolate()
a b
0 1.00 1.0
1 2.00 2.0
2 2.25 5.0
3 2.50 5.0
4 2.75 5.0
5 3.00 3.0
推荐阅读
- python - 使用 Python 扩展和 FFmpeg 时出现“分段错误(核心转储)”的原因
- javascript - Jest mock 静态成员的类方法
- excel - 如何使我的子过程动态循环通过一个范围?
- azure - 使用 Azure Devops CICD 使用 Terraform 部署 Azure SQL 数据对象
- ios - UITextField:attributeText 在 resignFirstResponder 时无法正常工作
- kubernetes - Kubernetes 作业和部署之间有什么区别
- conditional-statements - 根据谷歌电子表格上的名称计算总次数值
- ffmpeg - 不支持 ffmpeg 编解码器,找不到支持的设备
- java - Graphviz 异常 :: 提供的引擎都不能被初始化
- ffmpeg - 我有 2 个区域需要模糊 - 如何重复使用相同的滤镜?