有条件地将pandas.DataFrame中的值替换为先前的值

时间:2018-10-13 02:31:05

标签: python pandas

我需要过滤数据集中的异常值。在我的应用程序中,用列中的先前值替换异常值最有意义。

使用可用的pandas工具很难做到这一点(主要与切片上的副本或设置为NaN时发生的类型转换有关)。

是否有一种快速和/或内存有效的方法来做到这一点? (请参阅下面有关我当前使用的解决方案的回答,该解决方案也有局限性。)


一个简单的例子:

>>> import pandas as pd
>>> df = pd.DataFrame({'A':[1,2,3,4,1000,6,7,8],'B':list('abcdefgh')})
>>> df
      A  B
0     1  a
1     2  b
2     3  c
3     4  d
4  1000  e # '1000  e' --> '4  e'
5     6  f
6     7  g
7     8  h

2 个答案:

答案 0 :(得分:1)

您可以简单地掩盖阈值上的值并使用ffill

df.assign(A=df.A.mask(df.A.gt(10)).ffill())

     A  B
0  1.0  a
1  2.0  b
2  3.0  c
3  4.0  d
4  4.0  e
5  6.0  f
6  7.0  g
7  8.0  h

使用mask而不是使用shift之类的东西是必要的,因为它可以保证在先前值也高于阈值的情况下输出非离群值。

答案 1 :(得分:0)

我通过首先转换为pandas数组,在那里进行操作,然后重新插入列,来规避了numpy副本和切片的某些问题。我不确定,但是据我所知,一旦将数据类型放回到pandas.DataFrame中,数据类型就相同。

def df_replace_with_previous(df,col,maskfunc,inplace=False):
    arr = np.array(df[col])
    mask = maskfunc(arr)
    arr[ mask ] = arr[ list(mask)[1:]+[False] ]
    if inplace:
        df[col] = arr
        return
    else:
        df2 = df.copy()
        df2[col] = arr
        return df2

这将创建一个掩码,将其向下移动一个,以使True值指向上一个条目,并更新数组。当然,如果有多个相邻的异常值(如果有N个连续的异常值,则需要N次),这将需要递归运行。

在OP中给出的用法:

df_replace_with_previous(df,'A',lambda x:x>10,False)