仅当间隙小于 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
我正在使用一个 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