遍历数据帧时,代码花费的时间太长

时间:2018-08-06 22:44:18

标签: python pandas

signal = pd.DataFrame([[0, 0, 0],
                [-1, -1, -1],
                [1, 0, 0],
                [0, 0, 0],
                [1, 0, 0],
                [0, 1, 0],
                [0, 0, 1],
                [0, -1, 1],
                [-1, 0, 0],
                [0, 0, 0]],columns=['TKV','SWP','BWN'],index=date_index)

`
remove_duplicate(df,lookahead_days):
    df = df.copy()
    df.index = pd.to_datetime(df.index)
    for i in range(0, signal.shape[0], lookahead_days-1):
        date_range = df.index[i:i+lookahead_days]
        for col in df.columns:
            duplicates = df[col][date_range].duplicated(keep="first")
            duplicates_index = df[col][date_range][duplicates].index
            df.loc[duplicates_index, col] = 0
    df.index = df.index.date
    return df`        

我的目标是在几天(loookahead_days)的窗口中循环遍历信号数据帧,并检查是否存在重复项,然后将重复项设置为零,仅保留第一个。

我已经使用上面的函数完成了此操作,现在的问题是,当我将它传递通过形状大约为1000X500的真实数据帧时,运行时间太长了。

我想知道是否应该有更好的方法。

1 个答案:

答案 0 :(得分:0)

设置

from pandas import Timestamp
signal = pd.DataFrame({'TKV': {Timestamp('2018-01-01 00:00:00'): 0, Timestamp('2018-01-02 00:00:00'): -1, Timestamp('2018-01-03 00:00:00'): 1, Timestamp('2018-01-04 00:00:00'): 0, Timestamp('2018-01-05 00:00:00'): 1, Timestamp('2018-01-06 00:00:00'): 0, Timestamp('2018-01-07 00:00:00'): 0, Timestamp('2018-01-08 00:00:00'): 0, Timestamp('2018-01-09 00:00:00'): -1, Timestamp('2018-01-10 00:00:00'): 0}, 'SWP': {Timestamp('2018-01-01 00:00:00'): 0, Timestamp('2018-01-02 00:00:00'): -1, Timestamp('2018-01-03 00:00:00'): 0, Timestamp('2018-01-04 00:00:00'): 0, Timestamp('2018-01-05 00:00:00'): 0, Timestamp('2018-01-06 00:00:00'): 1, Timestamp('2018-01-07 00:00:00'): 0, Timestamp('2018-01-08 00:00:00'): -1, Timestamp('2018-01-09 00:00:00'): 0, Timestamp('2018-01-10 00:00:00'): 0}, 'BWN': {Timestamp('2018-01-01 00:00:00'): 0, Timestamp('2018-01-02 00:00:00'): -1, Timestamp('2018-01-03 00:00:00'): 0, Timestamp('2018-01-04 00:00:00'): 0, Timestamp('2018-01-05 00:00:00'): 0, Timestamp('2018-01-06 00:00:00'): 0, Timestamp('2018-01-07 00:00:00'): 1, Timestamp('2018-01-08 00:00:00'): 1, Timestamp('2018-01-09 00:00:00'): 0, Timestamp('2018-01-10 00:00:00'): 0}})

您可以在此处使用 drop_duplicates ,棘手的事情是您需要创建一个列,该列将从不不会在每个{{1 }}天的时间段(或您决定的任何时间分组)。假设您想删除重复项(如果它们在5天之内出现),我们需要创建一个在每个周期内都重复的列,我们可以将其用作n的键:

drop_duplicates

这给我们提供了一个列,该列在每个5天的时间段内始终是相同的,但是在检查重复项时可以用来区分 other 列。现在,我们要做的就是根据“标志”列以及我们要检查的其他列删除重复项:

s = (signal.reset_index()
        .groupby(pd.Grouper(freq='5d', key='index'))
        ['index'].transform('first')
    )

0   2018-01-01
1   2018-01-01
2   2018-01-01
3   2018-01-01
4   2018-01-01
5   2018-01-06
6   2018-01-06
7   2018-01-06
8   2018-01-06
9   2018-01-06
Name: index, dtype: datetime64[ns]

如果您不想删除重复项,而是想简单地将其替换为signal.assign(flag=s.values).drop_duplicates(['flag', 'TKV', 'SWP', 'BWN']).drop('flag', 1) TKV SWP BWN 2018-01-01 0 0 0 2018-01-02 -1 -1 -1 2018-01-03 1 0 0 2018-01-06 0 1 0 2018-01-07 0 0 1 2018-01-08 0 -1 1 2018-01-09 -1 0 0 2018-01-10 0 0 0 ,则可以在此处使用 0

duplicated

这导致第一组中的最后两个条目被删除,因为它们在该时间段内重复出现,但是第二组中的 not 行即使出现在第一组中也是如此。

这应该比您选择的要好得多:

tmp = signal.assign(flag=s.values)
tmp[tmp.duplicated()] = 0
tmp = tmp.drop('flag', 1)

            TKV  SWP  BWN
2018-01-01    0    0    0
2018-01-02   -1   -1   -1
2018-01-03    1    0    0
2018-01-04    0    0    0
2018-01-05    0    0    0
2018-01-06    0    1    0
2018-01-07    0    0    1
2018-01-08    0   -1    1
2018-01-09   -1    0    0
2018-01-10    0    0    0