Python 数据帧根据条件按上一行值更新行值
我有一个如下的数据帧。我想根据以下条件替换行值 如果3个连续的前一行值为0,则保持该值不变,或者如果只有一个前一行值为0,则通过该特定IEMI最后3行的滚动平均值填充该行 首先是Python 数据帧根据条件按上一行值更新行值,python,pandas,Python,Pandas,我有一个如下的数据帧。我想根据以下条件替换行值 如果3个连续的前一行值为0,则保持该值不变,或者如果只有一个前一行值为0,则通过该特定IEMI最后3行的滚动平均值填充该行 首先是数据帧(df) 请遵守预期KVA列的计算。由于第9行的实际KVA值为0,Expected KVA的值是IEMI 55647最近三次观测(KVA)的简单平均值。但在第3、第4和第5行,由于IEMI 55647的3KVA值为0,因此预期KVA值也为0 编辑 编辑-进一步 下面是一段伪代码片段。我有reset\u索引。但它可能
数据帧(df)
请遵守预期KVA
列的计算。由于第9行的实际KVA
值为0,Expected KVA
的值是IEMI 55647最近三次观测(KVA
)的简单平均值。但在第3、第4和第5行,由于IEMI 55647的3KVA
值为0,因此预期KVA
值也为0
编辑
编辑-进一步
下面是一段伪代码片段。我有reset\u索引
。但它可能不起作用
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进行了排序,因此索引被扭曲了
如何实现这一目标?与
groupby
功能耦合的循环?有什么想法吗 下面是我的想法:(我用IMEI:55674额外添加了3行,只是为了测试)
用一组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
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
用np.nan
分配剩余的0,用transform
执行groupby
,并用均值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
然后只需concat
和sort\u index
我们之前遗漏的内容:
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
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
@安德烈亚斯:我会更新相同的……不过,我们的想法是让社区成员得到答案。或者至少是每个人所说的方法。仅仅提到一些琐碎的问题或“降级”并没有帮助。@pythondumb:为什么您希望索引为0.0055469@anky_91:我错了,应该是1455.28。@pythondumb所以你的问题是得到滚动平均值还是否定3个一组的0.00?是的!!我会说“等同”而不是“否定”,谢谢。这似乎解决了我的问题。我可以使用rolling(window=3)代替transform('mean')
?@pythondumb。我还没有测试过,但是如果它返回相同的数据,你可以。:)