从熊猫数据框中删除“重叠”日期

埃里克·布朗

我有一个熊猫数据框,如下所示:

ID  date       close
1   09/15/07   123.45
2   06/01/08   130.13
3   10/25/08   132.01
4   05/13/09   118.34
5   11/07/09   145.99
6   11/15/09   146.73
7   07/03/11   171.10

我想删除任何重叠的行。

重叠的行定义为另一行X天之内的任何行。例如,如果X = 365,则结果应为:

ID  date       close
1   09/15/07   123.45
3   10/25/08   132.01
5   11/07/09   145.99
7   07/03/11   171.10

如果X = 50,则结果应为:

ID  date       close
1   09/15/07   123.45
2   06/01/08   130.13
3   10/25/08   132.01
4   05/13/09   118.34
5   11/07/09   145.99
7   07/03/11   171.10

我在这里看了几个问题,但是没有找到正确的方法。例如,熊猫检查重叠在多行日期最快的方法来消除特定日期从熊猫数据帧是相似的,但不完全得到我我需要什么。

我今天有下面的丑陋代码,适用于小的X值,但是当X变大时(例如,当X = 365时),它将删除除原始日期之外的所有日期。

filter_dates = []
for index, row in df.iterrows():
     if observation_time == 'D':
        for i in range(1, observation_period):
            filter_dates.append((index.date() + timedelta(days=i)))
df = df[~df.index.isin(filter_dates)]

任何帮助/指针将不胜感激!

澄清:

解决方案需要查看每一行,而不仅仅是第一行。

Quickbeam2k1

我只是使用了基本方法(本质上是OP方法的调整版本),没有花哨的numpy或pandas ops,而是线性的,而不是二次复杂的(与距离矩阵方法比较)。
但是(作为Cory Madden),我假设数据是相对于date列排序的。我希望它是正确的:

数据框->我在这里使用熊猫索引:

import pandas as pd
df = pd.DataFrame({'date': ["2007-09-15","2008-06-01","2008-10-25",
                            "2009-05-13","2009-11-07", "2009-11-15", "2011-07-03"],
                   'close':[123.45, 130.13, 132.01, 118.34, 
                            145.99, 146.73, 171.10]})
df["date"]=pd.to_datetime(df["date"])

以下代码块可以轻松地包装在函数中,并为X = 365计算正确的数据帧索引:

X = 365
filter_ids = [0]
last_day = df.loc[0, "date"]
for index, row in df[1:].iterrows():
     if (row["date"] - last_day).days > X:
         filter_ids.append(index)
         last_day = row["date"]

结果:

print(df.loc[filter_ids,:])
    close       date
0  123.45 2007-09-15
2  132.01 2008-10-25
4  145.99 2009-11-07
6  171.10 2011-07-03

请注意,由于索引从零开始,所以索引移位了一个。


我只是想评论线性与二次方的复杂度。我的解决方案具有线性时间复杂度,只能看到数据帧的每一行一次。Cory maddens解决方案具有二次复杂性:在每次迭代中,访问数据帧的每一行。但是,如果X(日差)很大,我们可能会丢弃仅执行很少迭代的数据集末端的很大一部分。

为此,可能要考虑以下针对X=2数据集的最坏情况

df = pd.DataFrame({'date':pd.date_range(start='01.01.1900', end='01.01.2100', freq='D')})

在我的机器上,以下代码产生:

%%timeit
X = 2
filter_ids = [0]
last_day = df.loc[0, "date"]
for index, row in df[1:].iterrows():
    if (row["date"] -last_day).days > X:
        filter_ids.append(index)
        last_day = row["date"]
1 loop, best of 3: 7.06 s per loop

day_diffs = abs(df.iloc[0].date - df.date).dt.days
i = 0
days = 2
idx = day_diffs.index[i]
good_ids = {idx}
while True:
    try:
        current_row = day_diffs[idx] 
        day_diffs = day_diffs.iloc[1:]
        records_not_overlapping = (day_diffs - current_row) > days         
        idx = records_not_overlapping[records_not_overlapping == True].index[0] 
        good_ids.add(idx)
except IndexError:  
    break
1 loop, best of 3: 3min 16s per loop

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章