根据pandas / python中的前一行值修改行值

时间:2018-02-22 18:06:17

标签: python-3.x pandas for-loop

我有一组非常大的数据帧,我想根据前面的行值和索引遵循一些逻辑进行修改。

如果值在要删除的值列表中,并且前一行的值不在要删除的值列表中,并且这两行具有相同的索引,则将前一个值分配给当前值。基本上我可以把它写成for循环并以下列方式获得所需的输出:

import pandas as pd

df = pd.DataFrame({'values': [1,2,3,4,2,4,4,1,2]},index=['A','A','A','A','B','B','B','C','C'])
print(df)

rem_val = [2,3]

for i in range(1,len(df)):
    if df['values'].iloc[i] in rem_val and df['values'].iloc[i-1] not in rem_val and df.index[i-1]==df.index[i]:
        df['values'].iloc[i]=df['values'].iloc[i-1]

print('After removal')

print(df)

输出为

   values
A       1
A       2
A       3
A       4
B       2
B       4
B       4
C       1
C       2
After removal
   values
A       1
A       1
A       1
A       4
B       2
B       4
B       4
C       1
C       1

请注意,例如,B的第一行是2(在要删除的列表中)但是因为在它之前没有B的行而停留。

不幸的是,这是一个相对较慢的代码(有数十亿行),但我不确定如何对其进行矢量化/更快。其中一个问题是,可能需要调整一行中有很多(10s)坏行,因此您无法将[:-1]与[1:]进行比较。有没有办法对上面的for循环进行矢量化/加速?

谢谢,

伊利亚安德

1 个答案:

答案 0 :(得分:1)

如果我理解清楚,请使用groupby + mask + isin

df.mask(df['values'].isin(rem_val)).groupby(level=0).ffill().combine_first(df)
Out[1572]: 
   values
A     1.0
A     1.0
A     1.0
A     4.0
B     2.0
B     4.0
B     4.0
C     1.0
C     1.0