根据前几行的值从数据框中过滤行

时间:2019-11-20 16:38:19

标签: python python-3.x pandas dataframe

我有一个如下数据框:

    A
1   1000
2   1000
3   1001
4   1001
5   10
6   1000
7   1010
8   9
9   10
10  6
11  999
12  10110
13  10111
14  1000 

我正尝试通过以下方式清理数据框: 对于每行的值大于前一行值的1.5倍或小于前一行值的0.5倍的行,请将其删除。 但是,如果前一行是拖放行,则必须与紧邻的前一个非拖放行进行比较。 (例如,我的数据框中的索引9、10或13) 所以最终的数据帧应该像这样:

    A
1   1000
2   1000
3   1001
4   1001
6   1000
7   1010
11  999
14  1000

我的数据帧非常大,因此性能受到赞赏。

2 个答案:

答案 0 :(得分:6)

您无法避免遍历每一行

提示
  • 避免为每一行创建新的(昂贵的)对象
  • 使用高效内存迭代

我会使用发电机

我将一个系列传递给一个函数,并产生满足条件的行的索引值。

def f(s):
    it = s.iteritems()
    i, v = next(it)
    yield i                          # Yield the first one
    for j, x in it:
        if .5 * v <= x <= 1.5 * v:
            yield j                  # Yield the ones that satisfy
            v = x                    # Update the comparative value

df.loc[list(f(df.A))]                # Use `loc` with index values
                                     # yielded by my generator

       A
1   1000
2   1000
3   1001
4   1001
6   1000
7   1010
11   999
14  1000

答案 1 :(得分:1)

一种替代方法是使用itertools.accumulate向前推最后一个有效值,然后过滤掉与原始值不同的值,例如:

from itertools import accumulate


def change(x, y, pct=0.5):
    if pct * x <= y <= (1 + pct) * x:
        return y
    return x

# create a mask filtering out the values that are different from the original A
mask = (df.A == list(accumulate(df.A, change)))

print(df[mask])

输出

       A
1   1000
2   1000
3   1001
4   1001
6   1000
7   1010
11   999
14  1000

只是个想法,请查看累计列(更改)与原始内容的比较:

        A  change
1    1000    1000
2    1000    1000
3    1001    1001
4    1001    1001
5      10    1001
6    1000    1000
7    1010    1010
8       9    1010
9      10    1010
10      6    1010
11    999     999
12  10110     999
13  10111     999
14   1000    1000

更新

要使其在函数调用中执行:

mask = (df.A == list(accumulate(df.A, lambda x, y : change(x, y, pct=0.5))))