我有一个pandas数据框,如下所示:
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
Run Code Online (Sandbox Code Playgroud)
我想删除任何重叠的行.
重叠行定义为另一行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
Run Code Online (Sandbox Code Playgroud)
如果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
Run Code Online (Sandbox Code Playgroud)
我在这里看了几个问题,但没有找到正确的方法.例如,Pandas检查多行中的重叠日期,最快的方法来消除熊猫数据帧中的特定日期是相似的,但不能完全得到我需要的东西.
我今天有以下丑陋的代码适用于小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)]
Run Code Online (Sandbox Code Playgroud)
任何帮助/指针将不胜感激!
澄清:
解决方案需要查看每一行,而不仅仅是第一行.
我只是使用了一种基本方法(本质上它是 OP 方法的调整版本),没有花哨的 numpy 或 pandas 操作,而是线性而不是二次复杂度(与距离矩阵方法相比)。
但是(作为 Cory Madden),我假设数据是根据日期列排序的。我希望它是正确的:
Dataframe -> 我在这里使用 pandas 索引:
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"])
Run Code Online (Sandbox Code Playgroud)
以下代码块可以轻松地包装在函数中,并计算 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"]
Run Code Online (Sandbox Code Playgroud)
结果:
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
Run Code Online (Sandbox Code Playgroud)
请注意,由于索引从零开始,索引会移动 1。
我只是想评论线性与二次复杂度我的解决方案具有线性时间复杂度,数据帧的每一行都恰好一次。Cory maddens 解决方案具有二次复杂度:在每次迭代中,数据帧的每一行都会被访问。然而,如果X(日差)很大,我们可能会丢弃数据集的很大一部分,而只执行很少的迭代。
为此,人们可能需要考虑X=2数据集的以下最坏情况:
df = pd.DataFrame({'date':pd.date_range(start='01.01.1900', end='01.01.2100', freq='D')})
Run Code Online (Sandbox Code Playgroud)
在我的机器上,以下代码产生:
%%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
Run Code Online (Sandbox Code Playgroud)
和
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
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
660 次 |
| 最近记录: |