You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas获取指定时间戳前1毫秒的最新ask_size值

需求:为DataFrame每行新增前1毫秒最新ask_size列

需要为DataFrame的每行新增一列,取值为该行event_timestamp前1毫秒时刻的最新ask_size值。示例规则:

  • 第1行前1毫秒的有效ask_size为165(尽管对应时间戳更早,但为该时刻的有效值)
  • 第3至8行前1毫秒的最新值均为203

示例表格

idx event_timestamp                 ask_size
0   2024-02-12 09:00:00.178941829   165
1   2024-02-12 09:00:00.334673928   166
2   2024-02-12 09:00:00.334723166   203
3   2024-02-12 09:00:00.339505589   203
4   2024-02-12 09:00:00.339517572   241
5   2024-02-12 09:00:00.339585194   276
6   2024-02-12 09:00:00.339597200   276
7   2024-02-12 09:00:00.339679756   277
8   2024-02-12 09:00:00.339705796   312
9   2024-02-12 09:00:00.343967540   275
10  2024-02-12 09:00:00.393306026   275

原始数据

import pandas as pd

data = {
    'event_timestamp': ['2024-02-12 09:00:00.178941829', '2024-02-12 09:00:00.334673928',
                        '2024-02-12 09:00:00.334723166', '2024-02-12 09:00:00.339505589',
                        '2024-02-12 09:00:00.339517572', '2024-02-12 09:00:00.339585194',
                        '2024-02-12 09:00:00.339597200', '2024-02-12 09:00:00.339679756',
                        '2024-02-12 09:00:00.339705796', '2024-02-12 09:00:00.343967540'],
    'ask_size_1_x': [165.0, 166.0, 203.0, 203.0, 241.0, 276.0, 276.0, 277.0, 312.0, 275.0]
}

df = pd.DataFrame(data)

尝试过的代码及问题

第一次尝试

data['1ms'] = data['event_timestamp'] - pd.Timedelta(milliseconds=1)

temp = data[['event_timestamp','ask_size_1']]
temp_time_shift = data[['1ms','ask_size_1']]

temp2 = pd.merge_asof(
            temp,
            temp_time_shift,
            left_on = 'event_timestamp',
            right_on = '1ms',
            direction='backward'
        )

未得到预期结果。

补充尝试

import pandas as pd

data = {
    'event_timestamp': [
        '2024-02-12 09:00:00.393306026',
        '2024-02-12 09:00:00.393347792',
        '2024-02-12 09:00:00.393351971',
        '2024-02-12 09:00:00.393355738',
        '2024-02-12 09:00:00.393389724',
        '2024-02-12 09:00:00.542780521',
        '2024-02-12 09:00:00.542841917',
        '2024-02-12 09:00:00.714845055',
        '2024-02-12 09:00:00.714908862',
        '2024-02-12 09:00:00.747016524'
    ],
    'ask_size_1': [275.0, 275.0, 237.0, 237.0, 202.0, 202.0, 202.0, 262.0, 261.0, 263.0]
}

df = pd.DataFrame(data)
df['event_timestamp'] = pd.to_datetime(df['event_timestamp'])  # 转换为datetime格式

tolerance = pd.Timedelta('1ms')
df['out'] = pd.merge_asof(df['event_timestamp'].sub(tolerance),
                          df[['event_timestamp', 'ask_size_1']],
                          direction='forward', tolerance=tolerance
                         )['ask_size_1']

得到的输出中第7行的out值与ask_size_1相同(为262),但预期应为第6行的202(即该行时间戳前1毫秒的最新值)。输出结果如下:

event_timestamp             ask_size_1  out
0   2024-02-12 09:00:00.393306026   275.0   275.0
1   2024-02-12 09:00:00.393347792   275.0   275.0
2   2024-02-12 09:00:00.393351971   237.0   275.0
3   2024-02-12 09:00:00.393355738   237.0   275.0
4   2024-02-12 09:00:00.393389724   202.0   275.0
5   2024-02-12 09:00:00.542780521   202.0   202.0
6   2024-02-12 09:00:00.542841917   202.0   202.0
7   2024-02-12 09:00:00.714845055   262.0   262.0
8   2024-02-12 09:00:00.714908862   261.0   262.0
9   2024-02-12 09:00:00.747016524   263.0   263.0

正确解决方案

核心逻辑是:为每行计算event_timestamp - 1ms作为目标时间,然后在原数据中找到小于等于该目标时间的最新ask_size值,使用merge_asof的backward方向即可实现,同时要确保时间列已转为datetime类型,且右表按时间排序(merge_asof要求右表必须排序)。

代码如下:

import pandas as pd

data = {
    'event_timestamp': [
        '2024-02-12 09:00:00.393306026',
        '2024-02-12 09:00:00.393347792',
        '2024-02-12 09:00:00.393351971',
        '2024-02-12 09:00:00.393355738',
        '2024-02-12 09:00:00.393389724',
        '2024-02-12 09:00:00.542780521',
        '2024-02-12 09:00:00.542841917',
        '2024-02-12 09:00:00.714845055',
        '2024-02-12 09:00:00.714908862',
        '2024-02-12 09:00:00.747016524'
    ],
    'ask_size_1': [275.0, 275.0, 237.0, 237.0, 202.0, 202.0, 202.0, 262.0, 261.0, 263.0]
}

df = pd.DataFrame(data)
# 转换时间列为datetime类型
df['event_timestamp'] = pd.to_datetime(df['event_timestamp'])
# 计算每行的目标时间:event_timestamp 减1毫秒
df['target_time'] = df['event_timestamp'] - pd.Timedelta(milliseconds=1)
# 右表必须按时间排序,merge_asof要求
right_df = df[['event_timestamp', 'ask_size_1']].sort_values('event_timestamp')
# 使用merge_asof匹配小于等于target_time的最新ask_size
result = pd.merge_asof(
    df[['target_time', 'event_timestamp', 'ask_size_1']],
    right_df,
    left_on='target_time',
    right_on='event_timestamp',
    direction='backward',
    suffixes=('', '_prev_1ms')
)
# 重命名结果列
result.rename(columns={'ask_size_1_prev_1ms': 'ask_size_prev_1ms'}, inplace=True)
# 查看结果
print(result[['event_timestamp', 'ask_size_1', 'ask_size_prev_1ms']])

结果说明

运行后第7行的ask_size_prev_1ms会是202,符合预期。因为该行的target_time是2024-02-12 09:00:00.713845055,原数据中小于等于该时间的最新记录是第6行的2024-02-12 09:00:00.542841917,对应ask_size_1为202。


内容的提问来源于stack exchange,提问作者IGottaLearnMath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 17:42:31