Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何删除Pandas中连续的坏数据点_Python_Pandas_Time Series_Sensors - Fatal编程技术网

Python 如何删除Pandas中连续的坏数据点

Python 如何删除Pandas中连续的坏数据点,python,pandas,time-series,sensors,Python,Pandas,Time Series,Sensors,我有一个熊猫数据框,看起来像: import pandas as pd import numpy as np df = pd.DataFrame({"Dummy_Var": [1]*12, "B": [6, 143.3, 143.3, 143.3, 3, 4, 93.9, 93.9, 93.9, 2, 2, 7], "C": [4.1, 23.2, 23.2, 23.2, 4.3, 2.5, 7.8, 7.8, 2,

我有一个熊猫数据框,看起来像:

import pandas as pd
import numpy as np
df = pd.DataFrame({"Dummy_Var": [1]*12, 
                   "B": [6, 143.3, 143.3, 143.3, 3, 4, 93.9, 93.9, 93.9, 2, 2, 7],
                   "C": [4.1, 23.2, 23.2, 23.2, 4.3, 2.5, 7.8, 7.8, 2, 7, 7, 7]})


    B       C       Dummy_Var
0   6.0     4.1     1
1   143.3   23.2    1
2   143.3   23.2    1
3   143.3   23.2    1
4   3.0     4.3     1
5   4.0     2.5     1
6   93.9    7.8     1
7   93.9    7.8     1
8   93.9    2.0     1
9   2.0     7.0     1
10  2.0     7.0     1
11  7.0     7.0     1
当同一数字连续出现三次或更多次时,该数据应替换为
NAN
。因此,结果应该是:

    B       C       Dummy_Var
0   6.0     4.1     1
1   NaN     NaN     1
2   NaN     NaN     1
3   NaN     NaN     1
4   3.0     4.3     1
5   4.0     2.5     1
6   NaN     7.8     1
7   NaN     7.8     1
8   NaN     2.0     1
9   2.0     NaN     1
10  2.0     NaN     1
11  7.0     NaN     1
我编写了一个函数,它可以:

def non_sense_remover(df, examined_columns, allowed_repeating):
    def count_each_group(grp, column):
        grp['Count'] = grp[column].count()
        return grp
    for col in examined_columns:
        sel = df.groupby((df[col] != df[col].shift(1)).cumsum()).apply(count_each_group, column=col)["Count"] > allowed_repeating
        df.loc[sel, col] = np.nan

    return df

df = non_sense_remover(df, ["B", "C"], 2)

然而,我真正的数据帧有2M行和18列!在2M行上运行此功能非常慢。有没有更有效的方法?我错过什么了吗?提前感谢。

我们正在使用
groupby
+
mask

m=df[['B','C']]
df[['B','C']]=m.mask(m.apply(lambda x : x.groupby(x.diff().ne(0).cumsum()).transform('count'))>2)
df
Out[1245]: 
      B    C  Dummy_Var
0   6.0  4.1          1
1   NaN  NaN          1
2   NaN  NaN          1
3   NaN  NaN          1
4   3.0  4.3          1
5   4.0  2.5          1
6   NaN  7.8          1
7   NaN  7.8          1
8   NaN  2.0          1
9   2.0  NaN          1
10  2.0  NaN          1
11  7.0  NaN          1

由此看来,使用apply/transform(在您的例子中是apply)是造成最大瓶颈的原因。我引用的链接更详细地介绍了这是为什么以及如何解决它

在这种情况下构建布尔掩码将比基于
apply()
的解决方案更有效,特别是对于大型数据集。以下是一种方法:

cols = df[['B', 'C']]
mask = (cols.shift(-1) == cols) & (cols.shift(1) == cols)

df[mask | mask.shift(1).fillna(False) | mask.shift(-1).fillna(False)] = np.nan

编辑:

对于更一般的方法,将长度为
N
的序列替换为
NaN
,您可以执行以下操作:

from functools import reduce
from operator import or_, and_

def replace_sequential_duplicates_with_nan(df, N):
    mask = reduce(and_, [cols.shift(i) == cols.shift(i + 1)
                         for i in range(N - 1)])
    full_mask = reduce(or_, [mask.shift(-i).fillna(False)
                             for i in range(N)])
    df[full_mask] = np.nan

这是一个迅速的解决办法。如果接受的限制是9,怎么办?i、 e.一行中有9个连续点是可以的,但只要有10个或更多点,我们就给它们分配
NaN
。我们能推广这种方法吗?谢谢你的编辑。这种方法花了22秒在我的2M行数据帧上完成任务,数据帧有18列。它非常优雅,我从中学到了很多东西。这种方法花了7秒钟在我的2M行数据框上完成任务,数据框有18列。如果您能在回答中详细说明为什么我的初始函数如此之慢,那就太好了。@ahoosh for loop是一个耗费时间的函数,如果您正在使用pandas,请尝试在这里不使用for loop