Python pandas 使用fillna方法填充特定值到单独一行

4

EDITED:

I have (not a very simple) a dataframe:

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.fillna(value='missing', limit=3) - EdChum
谢谢!我修改了我的问题,因为我使用了一个简单的 df,但是我在我的数据帧中有几个 NAN 块,所以我不知道 forwardlimit,只知道 backwardlimit1 - ragesz
3个回答

4

您可以在 df['att1'] 中计算NaN,然后减去1,将其用作参数limits传递给fillna函数。

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

编辑:

现在情况更加复杂。

首先,通过使用isnullshiftastypecumsum设置辅助列count来计算列att1的连续值。然后按照这个列count进行groupby并使用fillna填充数据:

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

1
谢谢!我使用了一个简单的 df 示例,但是当然我的数据框中有几个 NAN 值块,所以当我计算 limits 时,这个解决方案会失败 :( - ragesz

1
一种更简单的替代方法是创建一个索引点列表,其中包含您预期将出现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

谢谢!它也完美地工作了!!在Python 3中,可以使用range()函数。 - ragesz

0

将所有NaN值填充为"missing"。

最后一个"missing"可以替换为NaN。

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

使用负值作为iloc搜索索引可以向后查找。-2返回“att1”列中倒数第二个元素的值。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接