缺失值 NaN 替换条件 Python

Missing values NaN replace conditional Python

我有一个数据集,其中包含一系列国家和年份的几个指标的值(3072,1134 行和列),但有些为 NaN。

在下面找到数据集的样本:

Year Country Submitted Age12 Age14 ...
2017 CHI 1 267 136 ...
2018 CHI 1 267 NaN ...
2019 CHI NaN NaN NaN ...
2020 CHI 1 244 203 ...
2017 ALB 1 160 148 ...
2018 ALB 1 163 165 ...
2019 ALB 1 NaN NaN ...
2020 ALB 1 161 NaN ...
2017 GER 1 NaN 320 ...
2018 GER 1 451 381 ...
2019 GER NaN NaN NaN ...
2020 GER 1 361 321
2017 BRI 1 NaN NaN ...
2018 BRI 1 NaN NaN ...
2019 BRI NaN NaN NaN ...
2020 BRI 1 322 298

我想根据 Submitted 列的值替换缺失值。

仅当相应的 Submitted 值为“NaN”时,我才想更改前一行的值。

这就是我想要的:

Year Country Submitted Age12 Age14 ...
2017 CHI 1 267 136 ...
2018 CHI 1 267 NaN ...
2019 CHI 1 267 NaN ...
2020 CHI 1 244 203 ...
2017 ALB 1 160 148 ...
2018 ALB 1 163 165 ...
2019 ALB 1 NaN NaN ...
2020 ALB 1 161 NaN ...
2017 GER 1 NaN 320 ...
2018 GER 1 451 381 ...
2019 GER 1 451 381 ...
2020 GER 1 361 321 ...
2017 BRI 1 NaN NaN ...
2018 BRI 1 NaN NaN ...
2019 BRI 1 NaN NaN ...
2020 BRI 1 322 298

在社区的帮助下,我尝试使用

df = df.where(~df.Sumbitted.isnull(), df.fillna(axis=0, method='ffill'))

df = df.where(~df.Sumbitted.isnull(), df.fillna(axis=0, method='ffill',limit=2))

df = df.where(~df.Sumbitted.isnull(), interpolate(method="pad", limit=2))

但是,使用这些选项我得到以下结果。问题是代码检索了先前的非 NaN 值,但在先前值是 NaN 的情况下,代码检索先前值之前的值,直到找到非 NaN 值。

输出:

Year Country Submitted Age12 Age14 ...
2017 CHI 1 267 136 ...
2018 CHI 1 267 NaN ...
2019 CHI 1 267 136 ...
2020 CHI 1 244 203 ...
2017 ALB 1 160 148 ...
2018 ALB 1 163 165 ...
2019 ALB 1 NaN NaN ...
2020 ALB 1 161 NaN ...
2017 GER 1 NaN 320 ...
2018 GER 1 451 381 ...
2019 GER 1 451 381 ...
2020 GER 1 361 321
2017 BRI 1 NaN NaN ...
2018 BRI 1 NaN NaN ...
2019 BRI 1 361 321 ...
2020 BRI 1 322 298

查看 CHI 2019 Age14 和 BRI Age12 和 Age14 的错误输出

你知道如何通过修复这段代码来解决这个问题吗? 使用循环或选择这两列(Age14 和 Age12)的解决方案不是最优的,因为我有多个列(示例中的“...”)并且需要一个系统的解决方案。

谢谢

您可以使用参数 limit=1 来限制仅从前一行值开始填充,而不是进一步向上:

df = df.where(~df.Submitted.isnull(), df.fillna(axis=0, method='ffill',limit=1))

或者更好的是,简化您的代码,如下所示:

使用 .mask() instead of .where so that your code don't need extra step to negate the boolean mask. Also, use ffill() 这是 .fillna(axis=0, method='ffill') 的简化形式:

df = df.mask(df.Submitted.isna(), df.ffill(limit=1))

结果:

print(df)

    Year Country  Submitted  Age12  Age14
0   2017     CHI        1.0  267.0  136.0
1   2018     CHI        1.0  267.0    NaN
2   2019     CHI        1.0  267.0    NaN
3   2020     CHI        1.0  244.0  203.0
4   2017     ALB        1.0  160.0  148.0
5   2018     ALB        1.0  163.0  165.0
6   2019     ALB        1.0    NaN    NaN
7   2020     ALB        1.0  161.0    NaN
8   2017     GER        1.0    NaN  320.0
9   2018     GER        1.0  451.0  381.0
10  2019     GER        1.0  451.0  381.0
11  2020     GER        1.0  361.0  321.0
12  2017     BRI        1.0    NaN    NaN
13  2018     BRI        1.0    NaN    NaN
14  2019     BRI        1.0    NaN    NaN
15  2020     BRI        1.0  322.0  298.0