Pandas ffill限制的nan组仅限于限制

时间:2018-04-20 11:29:41

标签: python pandas nan

我希望在我的pandas数据框中向前填充一些值,但有限制。然而,该限制仅需要填充连续纳计数小于或等于极限的nans组。这是一个例子,

创建一个缺少数据的df,

import numpy as np
import pandas as pd

df = pd.DataFrame(
        {'val': [1, 1, np.nan, np.nan, 2, 3, np.nan, np.nan, np.nan, np.nan, 1, 1]}
)

print(df)

    val
0     1.0
1     1.0
2     NaN
3     NaN
4     2.0
5     3.0
6     NaN
7     NaN
8     NaN
9     NaN
10    1.0
11    1.0

现在,如果我们填充它,最多可以向前冲2步,

print(df.ffill(limit=2))

    val
0     1.0
1     1.0
2     1.0
3     1.0
4     2.0
5     3.0
6     3.0 #
7     3.0 #
8     NaN
9     NaN
10    1.0
11    1.0

当我不希望它们使用#fill读取时(上图)。我想要的是获得以下内容,

print(df.ffill(limit=2, dont_fill_any_nan_gaps_bigger_than_limit=True))

    val
0     1.0
1     1.0
2     1.0
3     1.0
4     2.0
5     3.0
6     NaN # 
7     NaN #
8     NaN 
9     NaN 
10    1.0
11    1.0

当然,这不需要是ffill中的单个参数,而是具有相同效果的参数。

3 个答案:

答案 0 :(得分:2)

如果您在使用ffill / pd.Series.mask / pd.Series.where后取消填充,则可以无条件np.where

v = df.value.isna()  # df.value.isnull()
df = df.ffill(limit=2).mask(
     v.groupby(v.ne(v.shift()).cumsum()).transform('size').gt(2)
)

    value
0     1.0
1     1.0
2     1.0
3     1.0
4     2.0
5     3.0
6     NaN
7     NaN
8     NaN
9     NaN
10    1.0
11    1.0

答案 1 :(得分:2)

创建掩码,按groupbytransform NaN过滤2size以及ffill ~的所有行,并应用a = df['value'].isna() a = a.ne(a.shift()).cumsum() m = (a.groupby(a).transform('size') > 2) df[~m] = df[~m].ffill(limit=2) print (df) value 0 1.0 1 1.0 2 1.0 3 1.0 4 2.0 5 3.0 6 NaN 7 NaN 8 NaN 9 NaN 10 1.0 11 1.0 仅适用于WMIC的反转条件的已过滤行:

@Echo Off
Set "VN="
For /F "EOL=V Tokens=*" %%A In (
    'WMIC OS Where "Version<'4'" Get Version 2^>Nul'
) Do For /F "Tokens=3 Delims=." %%B In ("%%A") Do Set "VN=%%B"
If Not Defined VN Exit /B
If %VN% GEq 11082 If %VN% LEq 16299 Set "VN="
If Defined VN Exit /B
Rem your install code goes here.

答案 2 :(得分:2)

我从灵感来自jezral到我之前的answerquestion获得了灵感,并将其应用于整个DataFrame。

我这样做是为了让我可以一次性处理整个DataFrame,这样每列都会ffill各自列中的缺失值(使用我的额外约束)。

设置DataFrame,

df = pd.DataFrame(
    {'val1': [1, 1, np.nan, np.nan, 2, 3, np.nan, np.nan, np.nan, np.nan, 1, 1],
     'val2': [1, 2, np.nan, np.nan, 2, 4, 4, np.nan, np.nan, np.nan, np.nan, 2]}
)

print(df)

    val1    val2
0   1.0     1.0
1   1.0     2.0
2   NaN     NaN
3   NaN     NaN
4   2.0     2.0
5   3.0     4.0
6   NaN #   4.0
7   NaN #   NaN #
8   NaN #   NaN #
9   NaN #   NaN #
10  1.0     NaN #
11  1.0     2.0

现在执行maskffill

mask_df = (
    df.isnull()
      .groupby([df.notnull().all(axis=1).cumsum()])
      .rank(method='max') - 1
).gt(2)

df = df.ffill().mask(mask_df)
print(df)

    val1    val2
0   1.0     1.0
1   1.0     2.0
2   1.0     2.0
3   1.0     2.0
4   2.0     2.0
5   3.0     4.0
6   NaN #   4.0
7   NaN #   NaN #
8   NaN #   NaN #
9   NaN #   NaN #
10  1.0     NaN #
11  1.0     2.0

<强>释

我们groupby使用非nan值的累积总和。这意味着nan值组合在一起。如果我们取这些rank的最大值,我们得到nan序列+ 1的长度。现在我们只使用mask函数,如cᴏʟᴅsᴘᴇᴇᴅanswer所示。