将 pandas 数据帧行移动到最近的时间步长
Posted
技术标签:
【中文标题】将 pandas 数据帧行移动到最近的时间步长【英文标题】:shift pandas dataframe rows to the nearest timestep 【发布时间】:2021-11-09 10:09:07 【问题描述】:背景
我有一个包含数百个数千个值的大型数据框。数据框的头部如下所示
df = pd.DataFrame([np.nan, 1100, 1400, np.nan, 14000],
index=pd.to_datetime(["2011-05-25 10:00:00",
"2011-05-25 16:40:00",
"2011-05-25 17:06:00",
"2011-05-25 17:10:00",
"2011-05-25 17:24:00"])
0
2011-05-25 10:00:00 NaN
2011-05-25 16:40:00 1100.0
2011-05-25 17:06:00 1400.0
2011-05-25 17:10:00 NaN
2011-05-25 17:24:00 14000.0
我想要什么
这些值并不总是以 6 分钟的时间步长记录。我想将未在 6 分钟时间步长记录的值移动到最近的 6 分钟步长。我希望新的数据框如下所示
n_df = pd.DataFrame([np.nan, 1100, 1400, np.nan, 14000],
index=pd.to_datetime(["2011-05-25 10:00:00",
"2011-05-25 16:42:00",
"2011-05-25 17:06:00",
"2011-05-25 17:12:00",
"2011-05-25 17:24:00"])
)
0
2011-05-25 10:00:00 NaN
2011-05-25 16:42:00 1100.0
2011-05-25 17:06:00 1400.0
2011-05-25 17:12:00 NaN
2011-05-25 17:24:00 14000.0
对我来说重要的是,n_df 中的所有值都应为 6 分钟时间步长,因此属性 n_df.index.freq
不得为 None
。
我怎样才能做到这一点。
到目前为止,我正在使用 for
循环通过迭代 df
并找到最近的 6 分钟步并将值移动/复制到该步,但如果 df
大于 1000,这将非常慢.
我尝试过的
index = pd.date_range(df.index[0], end=df.index[-1], freq="6min")
pydatetime_index = index.to_pydatetime()
n_df = pd.DataFrame(columns=df.columns, index=index)
for _idx, i in enumerate(df.index):
nearest_neighbor = np.abs(pydatetime_index - i.to_pydatetime())
idx = np.argmin(nearest_neighbor)
val = df.loc[i]
n_df.iloc[idx] = val
【问题讨论】:
而不是 argmin,它需要遍历整个index
,您只能遍历 -3 min、-2 min ... +2 min、+3 min 的偏移量。这应该会提高你的速度。如果您不介意每隔 6 分钟创建新的 nan 条目,您应该像下面@jazrael 的回答那样重新索引或重新采样。
【参考方案1】:
您可以使用merge_asof
和nearest
并指定tolerance
参数:
index = pd.date_range(df.index[0], end=df.index[-1], freq="6min")
df1 = pd.DataFrame(index=index)
df2 = pd.merge_asof(df1,
df,
left_index=True,
right_index=True,
direction='nearest',
tolerance=pd.Timedelta('3Min'))
print (df2)
0
2011-05-25 10:00:00 NaN
2011-05-25 10:06:00 NaN
2011-05-25 10:12:00 NaN
2011-05-25 10:18:00 NaN
2011-05-25 10:24:00 NaN
...
2011-05-25 17:00:00 NaN
2011-05-25 17:06:00 1400.0
2011-05-25 17:12:00 NaN
2011-05-25 17:18:00 NaN
2011-05-25 17:24:00 14000.0
[75 rows x 1 columns]
或与DataFrame.reindex
类似:
df2 = df.reindex(index, method='nearest', tolerance=pd.Timedelta('3Min'))
print (df2)
0
2011-05-25 10:00:00 NaN
2011-05-25 10:06:00 NaN
2011-05-25 10:12:00 NaN
2011-05-25 10:18:00 NaN
2011-05-25 10:24:00 NaN
...
2011-05-25 17:00:00 NaN
2011-05-25 17:06:00 1400.0
2011-05-25 17:12:00 NaN
2011-05-25 17:18:00 NaN
2011-05-25 17:24:00 14000.0
[75 rows x 1 columns]
或者:
df2 = df.resample('6Min').first()
print (df2)
0
2011-05-25 10:00:00 NaN
2011-05-25 10:06:00 NaN
2011-05-25 10:12:00 NaN
2011-05-25 10:18:00 NaN
2011-05-25 10:24:00 NaN
...
2011-05-25 17:00:00 NaN
2011-05-25 17:06:00 1400.0
2011-05-25 17:12:00 NaN
2011-05-25 17:18:00 NaN
2011-05-25 17:24:00 14000.0
[75 rows x 1 columns]
【讨论】:
非常感谢您的回答。有没有办法在你的答案中添加插值选项。例如,我们知道 16:40:00 的值是 1100,而 17:06:00 的值是 1400。我们是否可以将插值放在 16:42? @AtherCheema - 真的很复杂,你觉得this 吗?以上是关于将 pandas 数据帧行移动到最近的时间步长的主要内容,如果未能解决你的问题,请参考以下文章