【问题标题】:pandas map and timedelta with missing values缺少值的熊猫地图和时间增量
【发布时间】:2016-02-13 06:41:19
【问题描述】:

假设我有以下数据框 (df)

我想创建一个列来报告每个 ID 的连续时间戳之间的差异,这很简单:

df['time_diff'] = df.groupby('ID')['Timestamp'].diff()

产生

最后,我想创建另一个列hours_diff,它以小时为单位报告time_diff 中的值,以浮点数形式给出。忽略微秒精度,我试过了

df['hours_diff'] = df.time_diff.map(lambda t: t.days*24.0 + t.seconds/3600.0)

还有

df.loc[df.time_diff.notnull()==True,'hours_diff'] = df.loc[df.time_diff.notnull()==True].time_diff.map(lambda t: t.days*24.0 + t.seconds/3600.0)

这两个都给我

AttributeError: 'numpy.timedelta64' 对象没有属性 'days'。

但是,如果我运行命令

print set([type(i) for i in df.time_diff]),

它告诉我time_diff 列中的值的数据类型是pandas.tslib.Timedeltapandas.tslib.NaTType,它们似乎都不是numpy.timedelta64 类型。

【问题讨论】:

    标签: pandas timedelta


    【解决方案1】:

    当您迭代它们时,一系列 dtype timedelta64 产生 TimedeltaNaT,但像 .map()apply() 这样的函数会将它们视为 timedelta64

    您可以通过.dt 访问器在系列中使用Timedeltamethods:

    deltas = pd.date_range('2000-01-01', periods=10).to_series().diff()
    deltas
    
    2000-01-01      NaT
    2000-01-02   1 days
    2000-01-03   1 days
    2000-01-04   1 days
    2000-01-05   1 days
    2000-01-06   1 days
    2000-01-07   1 days
    2000-01-08   1 days
    2000-01-09   1 days
    2000-01-10   1 days
    Freq: D, dtype: timedelta64[ns]
    
    deltas.dt.days*24.0 + deltas.dt.seconds/3600.0
    
    2000-01-01   NaN
    2000-01-02    24
    2000-01-03    24
    2000-01-04    24
    2000-01-05    24
    2000-01-06    24
    2000-01-07    24
    2000-01-08    24
    2000-01-09    24
    2000-01-10    24
    Freq: D, dtype: float64
    

    更好:

    deltas.dt.total_seconds() / 3600.
    
    2000-01-01   NaN
    2000-01-02    24
    2000-01-03    24
    2000-01-04    24
    2000-01-05    24
    2000-01-06    24
    2000-01-07    24
    2000-01-08    24
    2000-01-09    24
    2000-01-10    24
    Freq: D, dtype: float64
    

    【讨论】:

    • 谢谢!您的建议非常适合问题中报告的数据框,只需稍作添加/修改: deltas = df['time_diff']; deltas_hours = deltas.dt.days*24.0 + deltas.dt.seconds/3600.0; df['hours_diff'] = deltas_hours; p.s.很抱歉回复晚了,我在这里很新,没想到会有这么及时和有用的答案。再次感谢!
    【解决方案2】:

    您可以将 timedelta64 除以 np.timedelta64(1,'s') 以获得以秒为单位的增量。如果您真的想摆脱微秒精度,只需将其四舍五入为 0 位并除以 3600 即可获得以小时为单位的增量。

    其实只有例子的倒数第二行是相关的,剩下的就是设置数据框。 (我将第二行更改为更精确的东西,我可以四舍五入。)

    import pandas as pd
    import numpy as np
    
    data = [{'ID': 'X', 'Timestamp': '2014-12-15 00:00:00', 'Quantity': 4},
            {'ID': 'X', 'Timestamp': '2014-12-15 01:25:00.435', 'Quantity': 7},
            {'ID': 'X', 'Timestamp': '2014-12-15 02:00:00', 'Quantity': 5},
            {'ID': 'X', 'Timestamp': '2014-12-15 03:00:00', 'Quantity': 5},
            {'ID': 'X', 'Timestamp': '2014-12-15 04:00:00', 'Quantity': 0},
            {'ID': 'Y', 'Timestamp': '2014-12-15 00:00:00', 'Quantity': 9},
            {'ID': 'Y', 'Timestamp': '2014-12-15 01:00:00', 'Quantity': 1},
            {'ID': 'Y', 'Timestamp': '2014-12-15 02:00:00', 'Quantity': 3},
            {'ID': 'Y', 'Timestamp': '2014-12-15 03:00:00', 'Quantity': 2},
            {'ID': 'Y', 'Timestamp': '2014-12-15 04:00:00', 'Quantity': 7},
           ]
    
    df = pd.DataFrame(data)
    df['Timestamp'] = pd.to_datetime(df['Timestamp'])
    
    df['time_diff'] = df.groupby('ID')['Timestamp'].diff()
    df['hour_diff'] = (df['time_diff']/np.timedelta64(1, 's')).round(0)/3600
    
    print(df)
    

    输出:

    ID 数量 时间戳 time_diff hour_diff 0 X 4 2014-12-15 00:00:00.000 NaT NaN 1 X 7 2014-12-15 01:25:00.435 01:25:00.435000 1.416667 2 X 5 2014-12-15 02:00:00.000 00:34:59.565000 0.583333 3 X 5 2014-12-15 03:00:00.000 01:00:00 1.000000 4 X 0 2014-12-15 04:00:00.000 01:00:00 1.000000 5 Y 9 2014-12-15 00:00:00.000 NaT NaN 6 是 1 2014-12-15 01:00:00.000 01:00:00 1.000000 7 是 3 2014-12-15 02:00:00.000 01:00:00 1.000000 8 是 2 2014-12-15 03:00:00.000 01:00:00 1.000000 9 是 7 2014-12-15 04:00:00.000 01:00:00 1.000000

    【讨论】:

    • 太棒了!谢谢,这很完美。为迟到的回复道歉,这里是全新的,没想到会得到如此及时和有用的答案。
    猜你喜欢
    • 2014-06-25
    • 2013-02-15
    • 1970-01-01
    • 2020-01-05
    • 2017-06-10
    • 2021-07-01
    • 1970-01-01
    • 2017-05-14
    相关资源
    最近更新 更多