我有一个Dataframe“timeseries”,它的索引是datetime,我有一个PeriodIndex“on”:
import numpy as np
import pandas as pd
timeseries = pd.DataFrame(
index=pd.DatetimeIndex(
[
"2000-01-01 12:00:00Z",
"2000-01-01 13:00:00Z",
"2000-01-01 14:00:00Z",
"2000-01-02 13:00:00Z",
"2000-01-02 18:00:00Z",
"2000-01-03 14:00:00Z",
"2000-01-03 20:00:00Z",
"2000-01-04 13:00:00Z",
]
),
data={
"value1": [6.0, 5.0, 3.0, 7.0, 4.0, 4.0, 5.0, 3.0],
},
)
on = pd.PeriodIndex(
["2000-01-01", "2000-01-02", "2000-01-04", "2000-01-05"], freq="D"
)
我想在“timeseries”中添加一列,其中包含每个相应日期时间所在的“on”中的时段:
value1 period
2000-01-01 12:00:00+00:00 6.0 2000-01-01
2000-01-01 13:00:00+00:00 5.0 2000-01-01
2000-01-01 14:00:00+00:00 3.0 2000-01-01
2000-01-02 13:00:00+00:00 7.0 2000-01-02
2000-01-02 18:00:00+00:00 4.0 2000-01-02
2000-01-03 14:00:00+00:00 4.0 NaN
2000-01-03 20:00:00+00:00 5.0 NaN
2000-01-04 13:00:00+00:00 3.0 2000-01-04
到目前为止,我已经用for循环实现了这一点:
timeseries["period"] = np.NaN
for period in on:
datetimes_in_period = timeseries.index[
(timeseries.index >= period.start_time.tz_localize("UTC"))
& (timeseries.index <= period.end_time.tz_localize("UTC"))
]
timeseries["period"].loc[datetimes_in_period] = period
为了提高效率,我想避免Python中的循环。我如何对这段代码进行向量化?
2条答案
按热度按时间eit6fx6z1#
您仍然可以按照@rorshan的建议使用
.merge_asof
。如果创建开始/结束间隔的 Dataframe :
bakd9h0s2#
我的解决方案是:
我以前从来没有使用过
PeriodIndex
,被迫用to_timestamp
将其转换为DateTimeIndex
。从文档中可以看出,PeriodIndex
似乎旨在以编程方式创建日期/时段(例如,两天之间的每X天),这似乎与它在这里的用途不太一样。无论如何,解决方案的核心是使用
merge_asof
,它类似于merge
,但不需要相等的键,它会查找最近的键。默认情况下,它会向后查找,这就是我们想要的(on
中最近的日期在timeseries
中的日期之前)。然后我们使用
groupby
和agg
来得到组。我们还需要获取
on
中与timeseries
(在本例中为2000-01-05
)不匹配的日期注意:你说你为了效率而“避免”循环,理论上这是个好主意,但要注意你试图实现的结果(将列表作为一列中的值)本身是相当低效的,在pandas
groupby
之上也是相当苛刻的。