首页 > 解决方案 > 将后续索引值之间经过的秒数分配给新列

问题描述

假设我有一个 Pandas 数据框,其中索引是日期时间值。我想添加一列,计算每个后续记录之间经过的总秒数。

问题设置:

import pandas as pd

df = pd.DataFrame(
    data=[
        ["2021-02-24 20:53:14.572000+00:00", "2362"],
        ["2021-02-24 21:02:28.567000+00:00", "4264"],
        ["2021-02-24 21:02:29.572000+00:00", "5160"],
        ["2021-02-24 21:02:30.561000+00:00", "6183"],
        ["2021-02-24 21:03:55.606000+00:00", "9654"],
    ],
    columns=["event_time", "some_metric"],
)

# Make the timestamp our index and make sure the events are in order.
df["event_time"] = pd.to_datetime(df["event_time"])
df = df.set_index("event_time")
df = df.sort_index()

所以现在我的数据框看起来像这样:

                                 some_metric
                      event_time    
2021-02-24 20:53:14.572000+00:00    2362
2021-02-24 21:02:28.567000+00:00    4264
2021-02-24 21:02:29.572000+00:00    5160
2021-02-24 21:02:30.561000+00:00    6183
2021-02-24 21:03:55.606000+00:00    9654

现在我想添加一个新列,它是直到下一个事件经过的秒数。

这是我正在尝试的,它运行没有错误::

df["seconds_until_next"] = (
    df.reset_index()["event_time"].shift(-1) - df.reset_index()["event_time"]
).dt.total_seconds()

但是生成的数据框看起来像这样,所有的 NaN 都在新列中:

                                 some_metric    seconds_until_next
                      event_time
2021-02-24 20:53:14.572000+00:00    2362              NaN
2021-02-24 21:02:28.567000+00:00    4264              NaN
2021-02-24 21:02:29.572000+00:00    5160              NaN
2021-02-24 21:02:30.561000+00:00    6183              NaN
2021-02-24 21:03:55.606000+00:00    9654              NaN

这很奇怪,因为只运行该操作的右侧看起来就像它返回了我想要的值:

(df.reset_index()["event_time"].shift(-1) - df.reset_index()["event_time"]).dt.total_seconds()

返回:

0    553.995
1      1.005
2      0.989
3     85.045
4        NaN
Name: event_time, dtype: float64

这里发生了什么?我认为这是因为等号左侧的df与右侧的结果之间的索引值不匹配?我该如何解决?

更新:这些答案很棒,希望我能给大家加分。我觉得我缺少的神奇知识是.to_series()。肯定会记住其他建议。这种方式在我的大脑中有效并且感觉良好,不确定它是否是性能最高的:

df["seconds_until_next"] = (
    df.index.to_series().shift(-1) - df.index.to_series()
).dt.total_seconds()

标签: pythonpandas

解决方案


一个类似(但稍微更简洁)的选项diff(而不是shifting 和减法):

df['seconds_until_next'] = -df.index.to_series().diff(-1).dt.total_seconds()

df

输出:

                                 some_metric  seconds_until_next
event_time                                                      
2021-02-24 20:53:14.572000+00:00        2362             553.995
2021-02-24 21:02:28.567000+00:00        4264               1.005
2021-02-24 21:02:29.572000+00:00        5160               0.989
2021-02-24 21:02:30.561000+00:00        6183              85.045
2021-02-24 21:03:55.606000+00:00        9654                 NaN

推荐阅读