在pandas数据框中填写缺少的中间值

时间:2016-06-14 20:37:07

标签: python pandas dataframe

我有一个pandas数据帧df

Date  cost    NC
20     5   NaN
21     7   NaN
23     9  78.0
25     6  80.0

现在我需要做的是填充缺少的日期,因此只有在前一行中有数字时才用x值填充列。那就是我希望输出像

Date  cost    NC
20     5   NaN
21     7   NaN
22     x   NaN
23     9  78.0
24     x   x
25     6  80.0

请参阅日期22缺失且21 NC缺失,因此22 cost分配给x,但NC已分配给NaN。现在将Date列设置为index并将reindex设置为缺失值,我可以到达此处

Date  cost    NC 
20     5.0   NaN
21     7.0   NaN
22     NaN   NaN
23     9.0  78.0
24     NaN   NaN
25     6.0  80.0

但是我无法达到最终输出。如果您这样想,就像ffill()一样,但不必填写前一行,您必须将x放在此处。

我有另一个问题。在这里,我有一个像这样的数据框df

Date type  cost
10    a    30
11    a    30
11    b    25
13    a    27

在这里,我还要填写缺失的值并使其像这样

Date type cost
10    a   30
11    a   30
11    b   25
12    a   30
12    b   25
13    a   27

你可以看到日期11有2个数据行所以都被复制到12个。我为这个问题编写了这个程序

missing=[12]
for i in missing:
    new_date=i
    i-=1        #go to previous date
    k=df[df["Date"] == i].index.tolist()[-1]+1 #index where to be filled
    data=pd.DataFrame(df[df["Date"] == i].values,columns=df.columns)
    data["Date"]=new_date
    df=pd.concat([df.iloc[:k],data,df.iloc[k:]]).reset_index(drop=True)

现在对于大型数据集,上述程序需要花费大量时间,因为每次都需要找到索引和concat 3数据帧。有没有更好更有效的方法来解决这个问题?

1 个答案:

答案 0 :(得分:1)

我认为没有办法只填充“中间”值,但这是一种方法(使用ffillbfillfillna):< / p>

In [11]: df1  # assuming Date is the index via df.set_index("Date")
Out[11]:
      cost    NC
Date
20       5   NaN
21       7   NaN
23       9  78.0
25       6  80.0

In [12]: df2 = df1.reindex(np.arange(20,27))
         # 26 is sufficient, but let's see it working!

In [13]: df2
Out[13]:
      cost    NC
Date
20     5.0   NaN
21     7.0   NaN
22     NaN   NaN
23     9.0  78.0
24     NaN   NaN
25     6.0  80.0
26     NaN   NaN

你不想填写“外部”NaN,可以使用:

In [14]: df2.bfill().notnull() & df2.ffill().notnull()
Out[14]:
       cost     NC
Date
20     True  False
21     True  False
22     True  False
23     True   True
24     True   True
25     True   True
26    False  False

现在,我们可以更新这些内容(如果它们将使用fillna进行更新):

In [15]: df2[df2.bfill().notnull() & df2.ffill().notnull()] = df2.fillna(0) # x = 0

In [16]: df2
Out[15]:
      cost    NC
Date
20     5.0   NaN
21     7.0   NaN
22     0.0   NaN
23     9.0  78.0
24     0.0   0.0
25     6.0  80.0
26     NaN   NaN

要(部分地)回答第二个问题,IMO在这种情况下你最好总是以一个支点开始(这会给你一个更好的起点):

In [21]: df
Out[21]:
   Date type  cost
0    10    a    30
1    11    a    30
2    11    b    25
3    13    a    27

In [22]: df.pivot_table("cost", "Date", "type")
Out[22]:
type     a     b
Date
10    30.0   NaN
11    30.0  25.0
13    27.0   NaN

也许你想从那里填补? (并在必要时拆开)。