Python pandas 仅填充一行具有特定值

Python pandas fillna only one row with specific value

已编辑:

我有一个(不是很简单的)数据框:

df = pd.DataFrame([1, 2, np.nan, np.nan, np.nan, np.nan, 3, 4
    , np.nan, np.nan, np.nan, 5], columns=['att1'])

     att1
0  1.0000
1  2.0000
2     nan
3     nan
4     nan
5     nan
6  3.0000
7  4.0000
8     nan
9     nan
10    nan
11 5.0000

我想用除最后一个 NAN 值之外的前一个非 NAN 值填充 NAN 值。我希望填充后的最后一个 NAN 值为 NAN。我该怎么做?

我想要这个结果:

     att1
0  1.0000
1  2.0000
2  2.0000
3  2.0000
4  2.0000
5     nan
6  3.0000
7  4.0000
8  4.0000
9  4.0000
10    nan
11 5.0000

我试过这个:

df = df.fillna(value='missing', method='bfill', limit=1)
df = df.fillna(method='ffill')

但是第一行给出了这个错误:

ValueError: cannot specify both a fill method and value

为什么 pandas 0.17.1 / Python 3.5 有这个限制? 谢谢!

您可以在 df['att1'] 中计算 NaN,减去 1 然后它用作参数 limitsfillna:

import pandas as pd
import numpy as np

df = pd.DataFrame([1, 2, np.nan, np.nan, np.nan, np.nan, 3] , columns=['att1'])
print df
   att1
0     1
1     2
2   NaN
3   NaN
4   NaN
5   NaN
6     3

s = df['att1'].isnull().sum() - 1
df['att1'] = df['att1'].fillna('missing', limit=s)
print df
      att1
0        1
1        2
2  missing
3  missing
4  missing
5      NaN
6        3

编辑:

现在更复杂了。

因此,首先设置辅助列 count 以通过 isnull[= 计算列 att1 的连续值24=]astypecumsum。然后 groupby 通过此列 countfillna:

import pandas as pd
import numpy as np

df = pd.DataFrame([1, 2, np.nan, np.nan, np.nan, np.nan, 3, 4
    , np.nan, np.nan, np.nan, 5], columns=['att1'])
print df

df['count'] = (df['att1'].isnull() != df['att1'].isnull().shift()).astype(int).cumsum()
print df
    att1  count
0      1      1
1      2      1
2    NaN      2
3    NaN      2
4    NaN      2
5    NaN      2
6      3      3
7      4      3
8    NaN      4
9    NaN      4
10   NaN      4
11     5      5
def f(x):
    att = x['att1'].isnull()
    if(att.all()):
        return x['att1'].fillna('missing', limit=att.sum() - 1)
    else:
        return x['att1']

print df.groupby(['count']).apply(f).reset_index(drop=True)

0           1
1           2
2     missing
3     missing
4     missing
5         NaN
6           3
7           4
8     missing
9     missing
10        NaN
11          5
Name: att1, dtype: object

解释列 count

print (df['att1'].isnull() != df['att1'].isnull().shift())
0      True
1     False
2      True
3     False
4     False
5     False
6      True
7     False
8      True
9     False
10    False
11     True
Name: att1, dtype: bool
print (df['att1'].isnull() != df['att1'].isnull().shift()).astype(int)
0     1
1     0
2     1
3     0
4     0
5     0
6     1
7     0
8     1
9     0
10    0
11    1
Name: att1, dtype: int32
print (df['att1'].isnull() != df['att1'].isnull().shift()).astype(int).cumsum()
0     1
1     1
2     2
3     2
4     2
5     2
6     3
7     3
8     4
9     4
10    4
11    5
Name: att1, dtype: int32

另一种可能不太复杂的方法是创建一个索引点列表,您希望在该列表中存在 NaN(其中索引点不为空,但之前的索引点为空).然后您只需向前填充您的数据并使用您创建的列表重新插入 NaN。

import pandas as pd
import numpy as np
from numpy import nan as NA
df = pd.DataFrame([1, 2, np.nan, np.nan, np.nan, np.nan, 3, 4
    , np.nan, np.nan, np.nan, 5], columns=['att1'])

#create list of index points where you want NaNs to be be
Nan_ind = [x - 1 for x in xrange(1, df.index[-1] + 1) 
                if pd.notnull(df.loc[x, 'att1'])
                and pd.isnull(df.loc[x-1, 'att1'])]

#forward fillna             
df['att1'] = df['att1'].fillna(method = 'ffill')

#reinsert NaNs using your list of index points
df.loc[Nan_ind, 'att1'] = NA

用 "missing" 填充所有 NaN。 最后一个 "missing" 可以用 NaN 代替。

df['att1'].fillna("missing",inplace=True)
df.iloc[[-2]].replace("missing",NaN)

对 iloc 反向搜索索引使用负值。 -2 return 'att1' 列的前一个元素的值。