Pandas Dataframe根据条件通过上一个更新行值

时间:2019-01-10 02:12:50

标签: python pandas

我有一个如下数据框。我想根据以下条件替换行值。

如果3个连续的前一行值是0,则将其保持不变,或者如果只有一个前一行值是0,则通过对该特定IEMI的最后3行进行均值滚动来填充该行。

首先是dataframe (df)

IMEI        KVA          KwH            Expected KVA
55647     1307.65       1020.33            1307.65
55468     2988.00       1109.05            2988.00
55647     0.00          977.87             0.00
55467     0.00          1388.25            0.00
55647     0.00          445.37             0.00
55469     1888.97       933.48             1888.97
55647     1338.65       1120.33            1338.65
55468     2088.00       1019.05            2088.00
55647     0.00          977.87             =(1307.65+0.00+1338.65)/3=882.1
55469     1455.28       1388.25            1455.28
55648     2144.38       445.37             2144.38
55469     1888.97       933.48             1888.97

请注意Expected KVA列的计算。由于第9行的实际KVA值是0,因此Expected KVA的值是IEMI 55647的最后三个观察值(KVA)的简单平均值。但是在第3、4和5行, IEMI 55647的3个KVA值是0,因此Expected KVA的值也是0。

修改 编辑-进一步 以下是伪代码段。我有reset_index。仍然可能不起作用

df = df.sort_values(['IMEI'],ascending=0).reset_index(drop=True)
for i in range(0,len(df)):
     if df.loc[i:i+2,'KVA']==0:
          df['Expected KVA'] = df['KVA']
     else:
        df['Expected KVA']=df.groupby('IEMI')['KVA'].rolling(min_periods=1,center=True,window=3).mean()

我相信上述代码段可能会因为我对IEMI进行排序而失败,从而导致索引失真。

如何实现? for循环与groupby函数耦合?有什么想法吗?

1 个答案:

答案 0 :(得分:1)

下面是我的想法:(我在IMEI中增加了3行:55674仅用于测试)

使用3组(无需任何操作)删除连续的0,并在数据帧上切片:

import itertools
def consecutive(data, stepsize=1):
    return np.split(data, np.where(np.diff(data) != stepsize)[0]+1)

a = np.array(df[df.KVA == 0.00].index)
l = consecutive(a)
to_exclude=list(itertools.chain.from_iterable([i.tolist() for i in l if len(i)==3]))
pd.options.mode.chained_assignment = None
df1 = df.loc[~df.index.isin(to_exclude)]
>>df1
    IMEI    KVA     KwH
0   55647   1307.65 1020.33
1   55468   2988.00 1109.05
5   55469   1888.97 933.48
6   55647   1338.65 1120.33
7   55468   2088.00 1019.05
8   55647   0.00    977.87
9   55469   1455.28 1388.25
10  55648   2144.38 445.37
11  55469   1888.97 933.48
12  55674   0.00    6433.00
13  55674   1345.00 6542.00
14  55674   3456.00 6541.00

np.nan分配剩余的0,并用均值groupbytransform进行fillna

df1['KVA'] = df1['KVA'].replace(0, np.nan)
df1['KVA'] = df1['KVA'].fillna(df1.fillna(0).groupby(['IMEI'])['KVA'].transform('mean'))
>>df1
    IMEI    KVA          KwH
0   55647   1307.650000 1020.33
1   55468   2988.000000 1109.05
5   55469   1888.970000 933.48
6   55647   1338.650000 1120.33
7   55468   2088.000000 1019.05
8   55647   882.100000  977.87
9   55469   1455.280000 1388.25
10  55648   2144.380000 445.37
11  55469   1888.970000 933.48
12  55674   1600.333333 6433.00
13  55674   1345.000000 6542.00
14  55674   3456.000000 6541.00

然后只concatsort_index我们先前遗漏的那些:

pd.concat([df1,df.loc[df.index.isin(to_exclude)]]).sort_index()

    IMEI    KVA         KwH
0   55647   1307.650000 1020.33
1   55468   2988.000000 1109.05
2   55647   0.000000    977.87
3   55467   0.000000    1388.25
4   55647   0.000000    445.37
5   55469   1888.970000 933.48
6   55647   1338.650000 1120.33
7   55468   2088.000000 1019.05
8   55647   882.100000  977.87
9   55469   1455.280000 1388.25
10  55648   2144.380000 445.37
11  55469   1888.970000 933.48
12  55674   1600.333333 6433.00
13  55674   1345.000000 6542.00
14  55674   3456.000000 6541.00