【问题标题】:Convert pandas DateTimeIndex to Unix Time?将熊猫 DateTimeIndex 转换为 Unix 时间?
【发布时间】:2013-02-18 15:54:45
【问题描述】:

将 pandas DateTimeIndex 转换为(可迭代的)Unix 时间的惯用方法是什么? 这可能不是要走的路:

[time.mktime(t.timetuple()) for t in my_data_frame.index.to_pydatetime()]

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    注意:时间戳只是 unix 时间,单位为纳秒(所以除以 10**9):

    [t.value // 10 ** 9 for t in tsframe.index]
    

    例如:

    In [1]: t = pd.Timestamp('2000-02-11 00:00:00')
    
    In [2]: t
    Out[2]: <Timestamp: 2000-02-11 00:00:00>
    
    In [3]: t.value
    Out[3]: 950227200000000000L
    
    In [4]: time.mktime(t.timetuple())
    Out[4]: 950227200.0
    

    正如@root 指出的那样,直接提取值数组会更快:

    tsframe.index.astype(np.int64) // 10 ** 9
    

    【讨论】:

    • 这非常简单……(我可以发誓我尝试了 t.value,结果我只尝试了 tsframe.index.value)
    • @ChristianGeier 只有知道答案才容易! tsframe.index.values 与众不同真是太疯狂了……令人困惑。
    【解决方案2】:

    由于 DatetimeIndexndarray 在引擎盖下,您可以在没有理解的情况下进行转换(更快)。

    In [1]: import numpy as np
    
    In [2]: import pandas as pd
    
    In [3]: from datetime import datetime
    
    In [4]: dates = [datetime(2012, 5, 1), datetime(2012, 5, 2), datetime(2012, 5, 3)]
       ...: index = pd.DatetimeIndex(dates)
       ...: 
    In [5]: index.astype(np.int64)
    Out[5]: array([1335830400000000000, 1335916800000000000, 1336003200000000000], 
            dtype=int64)
    
    In [6]: index.astype(np.int64) // 10**9
    Out[6]: array([1335830400, 1335916800, 1336003200], dtype=int64)
    
    %timeit [t.value // 10 ** 9 for t in index]
    10000 loops, best of 3: 119 us per loop
    
    %timeit index.astype(np.int64) // 10**9
    100000 loops, best of 3: 18.4 us per loop
    

    【讨论】:

    • 我很恼火,我不记得如何将其作为数组访问,当然是.as_type(int64) :)
    • @AndyHayden -- 通常情况正好相反 :)
    • 如果不清楚,index.astype(np.int64) 会返回以纳秒为单位的时间,而不是秒。
    • 有没有办法用这种方法保存 NaT 或 NaN?否则你会得到一个很大的负值。
    【解决方案3】:

    其他答案的总结:

    df['<time_col>'].astype(np.int64) // 10**9
    

    如果您想保持毫秒除以 10**6 而不是

    【讨论】:

      【解决方案4】:

      补充其他答案://10**9 将做一个地板除法,它给出过去的完整秒数,而不是最接近的秒值。如果需要,获得更合理舍入的一种简单方法是在进行地板除法之前添加5*10**8 - 1

      【讨论】:

        【解决方案5】:

        为了解决 NaT 的情况,上面的解决方案将转换为大的负整数,在 pandas>=0.24 中,一个可能的解决方案是:

        def datetime_to_epoch(ser):
            """Don't convert NaT to large negative values."""
            if ser.hasnans:
                res = ser.dropna().astype('int64').astype('Int64').reindex(index=ser.index)
            else:
                res = ser.astype('int64')
        
            return res // 10**9
        

        在缺少值的情况下,这将返回可为空的 int 类型“Int64”(ExtensionType pd.Int64Dtype):

        In [5]: dt = pd.to_datetime(pd.Series(["2019-08-21", "2018-07-28", np.nan]))                                                                                                                                                                                                    
        In [6]: datetime_to_epoch(dt)                                                                                                                                                                                                                                                   
        Out[6]: 
        0    1566345600
        1    1532736000
        2           NaN
        dtype: Int64
        

        否则为常规 int64:

        In [7]: datetime_to_epoch(dt[:2])                                                                                                                                                                                                                                               
        Out[7]: 
        0    1566345600
        1    1532736000
        dtype: int64
        

        【讨论】:

          【解决方案6】:

          如果您在数据框的日期时间列上尝试过此操作:

          dframe['datetime'].astype(np.int64) // 10**9
          

          & 你正在努力解决以下错误:TypeError: int() argument must be a string, a bytes-like object or a number, not 'Timestamp' 你可以使用这两行:

          dframe.index = pd.DatetimeIndex(dframe['datetime'])
          dframe['datetime']= dframe.index.astype(np.int64)// 10**9
          

          【讨论】:

            【解决方案7】:

            其他答案的代码

            dframe['datetime'].astype(np.int64) // 10**9
            

            在我发帖时打印以下警告:

            FutureWarning:将 datetime64[ns] 值转换为 int64 .astype(...) 已弃用,并将在未来版本中提出。采用 .view(...) 代替。

            所以请改用以下内容:

            dframe['datetime'].view(np.int64) // 10 ** 9
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-05-19
              • 2016-03-27
              • 1970-01-01
              • 2021-01-22
              • 2013-05-13
              • 1970-01-01
              • 2021-12-07
              相关资源
              最近更新 更多