Mar*_*rkD 5 python dataframe pandas
我有日期范围(实际数据帧附加了更多的数据,但具有相同的数据帧start和end列)。最终需要在周日至周六的基础上逐周分析数据。因此,我想通过 DataFrame,并拆分从星期六到星期日的任何日期范围 ( startto finish)。例如,给定 DataFrame:
import pandas as pd
date_ranges = [
{'start': '2020-01-16 22:30:00', 'end': '2020-01-17 01:00:00'}, # spans thurs-fri, ok as is
{'start': '2020-01-17 04:30:00', 'end': '2020-01-17 12:30:00'}, # no span, ok as is
{'start': '2020-01-18 10:15:00', 'end': '2020-01-18 14:00:00'}, # no span, ok as is
{'start': '2020-01-18 22:30:00', 'end': '2020-01-19 02:00:00'} # spans sat-sun, must split
]
data_df = pd.DataFrame(date_ranges)
Run Code Online (Sandbox Code Playgroud)
我希望我的结果看起来像:
result_ranges = [
{'start': '2020-01-16 22:30:00', 'end': '2020-01-17 01:00:00'}, # spans thurs-fri, ok as is
{'start': '2020-01-17 04:30:00', 'end': '2020-01-17 12:30:00'}, # no span, ok as is
{'start': '2020-01-18 10:15:00', 'end': '2020-01-18 14:00:00'}, # no span, ok as is
{'start': '2020-01-18 22:30:00', 'end': '2020-01-19 00:00:00'}, # split out saturday portion
{'start': '2020-01-19 00:00:00', 'end': '2020-01-19 02:00:00'} # and the sunday portion
]
result_df = pd.DataFrame(result_ranges)
Run Code Online (Sandbox Code Playgroud)
关于如何在熊猫中有效地做到这一点的任何想法将不胜感激。目前我正在做坏事,并迭代行,当数据集变大时,速度很慢。
像这样的操作总是很困难,在某种程度上我认为循环是必要的。在这种情况下,我们可以在边缘上循环而不是在行上循环。当您的数据跨度的周数远小于您拥有的行数时,这应该会带来相当大的性能提升。
我们定义边并在必要时修改 DataFrame 端点。最后,所需的 DataFrame 是我们修改的 DataFrame 的剩余部分,加上我们存储在l. 原始索引被保留,因此您可以确切地看到哪些行被拆分。如果单个时间跨度跨越N边缘,它将被分成N+1单独的行。
import pandas as pd
df[['start', 'end']]= df[['start', 'end']].apply(pd.to_datetime)
edges = pd.date_range(df.start.min().normalize() - pd.Timedelta(days=7),
df.end.max().normalize() + pd.Timedelta(days=7), freq='W-Sun')
Run Code Online (Sandbox Code Playgroud)
l = []
for edge in edges:
m = df.start.lt(edge) & df.end.gt(edge) # Rows to modify
l.append(df.loc[m].assign(end=edge)) # Clip end of modified rows
df.loc[m, 'start'] = edge # Fix start for next edge
result = pd.concat(l+[df]).sort_values('start')
Run Code Online (Sandbox Code Playgroud)
start end
0 2020-01-16 22:30:00 2020-01-17 01:00:00
1 2020-01-17 04:30:00 2020-01-17 12:30:00
2 2020-01-18 10:15:00 2020-01-18 14:00:00
3 2020-01-18 22:30:00 2020-01-19 00:00:00
3 2020-01-19 00:00:00 2020-01-19 02:00:00
Run Code Online (Sandbox Code Playgroud)