仅当间隙小于 N nans 时才在 pandas df 中填充 nan 间隙

Fill nan gaps in pandas df only if gaps smaller than N nans

我正在使用一个 pandas 数据框,其中也包含 nan 值。我想用 df.interpolate 替换带有插值的 nans,但前提是 nan 值序列的长度为 =

print(df)
A   B   C
1   1   1
nan nan 2
nan nan 3
nan 4   nan
5   5   5

在这种情况下,我想在 df 上应用一个函数,只填充长度为 N<=2 的 nan 序列,但较大的序列保持不变,从而得到我想要的输出

print(df)
A   B   C
1   1   1
nan 2   2
nan 3   3
nan 4   4
5   5   5

注意,我知道df.interpolate里面有limit=N的选项,但是它不能满足我的要求,因为它会填充任意长度的nan序列,只是限制填充前 3 个 nans 导致不希望的输出

print(df)
A   B   C
1   1   1
2   2   2
3   3   3
nan 4   4
5   5   5

那么你知道一个函数/你知道如何构造一个代码来产生我想要的输出吗?发送

尝试:

N = 2
df_interpolated = df.interpolate()

for c in df:
    mask = df[c].isna()
    x = (
        mask.groupby((mask != mask.shift()).cumsum()).transform(
            lambda x: len(x) > N
        )
        * mask
    )
    df_interpolated[c] = df_interpolated.loc[~x, c]

print(df_interpolated)

打印:

     A    B    C
0  1.0  1.0  1.0
1  NaN  2.0  2.0
2  NaN  3.0  3.0
3  NaN  4.0  4.0
4  5.0  5.0  5.0

尝试不同 df:

     A    B    C
0  1.0  1.0  1.0
1  NaN  NaN  2.0
2  NaN  NaN  3.0
3  NaN  4.0  NaN
4  5.0  5.0  5.0
5  NaN  5.0  NaN
6  NaN  5.0  NaN
7  8.0  5.0  NaN

产生:

     A    B    C
0  1.0  1.0  1.0
1  NaN  2.0  2.0
2  NaN  3.0  3.0
3  NaN  4.0  4.0
4  5.0  5.0  5.0
5  6.0  5.0  NaN
6  7.0  5.0  NaN
7  8.0  5.0  NaN

您可以尝试以下方法-

n=2
cols = df.columns[df.isna().sum()<=n]
df[cols]  = df[cols].interpolate()
df
     A    B    C
0  1.0  1.0  1.0
1  NaN  2.0  2.0
2  NaN  3.0  3.0
3  NaN  4.0  4.0
4  5.0  5.0  5.0

df.columns[df.isna().sum()<=n] 根据您的条件过滤列。然后,您只需在插值后覆盖列即可。

您可以执行 运行 长度编码并识别 NaN 的 运行 中每列短于或等于两个元素的元素。一种方法是使用包 pdrle 中的 get_id(免责声明:我写的)。

import pdrle


chk = df.isna() & (df.apply(lambda x: x.groupby(pdrle.get_id(x)).transform(len)) <= 2)
df[chk] = df.interpolate()[chk]
#      A    B    C
# 0  1.0  1.0  1.0
# 1  NaN  2.0  2.0
# 2  NaN  3.0  3.0
# 3  NaN  4.0  4.0
# 4  5.0  5.0  5.0