【问题标题】:How to use just the time part of a datetime in python? [duplicate]如何在python中仅使用日期时间的时间部分? [复制]
【发布时间】:2020-01-20 16:14:39
【问题描述】:

我正在使用一些日期和时间变量,但我只想使用时间部分。

例如,某列A和B当我做'dtypes'时,两者都显示“dtype('O')”,但A的输出是:

0        2017-11-29 17:14:00
1        2017-02-15 15:35:00
2        2018-10-18 08:02:00
3        2017-06-22 09:25:00

对于 B 是:

0        2017-11-29 20:00:00
1        2017-02-15 16:43:00
2        2018-10-18 11:08:00
3        2017-06-22 11:29:00

然后我这样做:

import datetime
from datetime import datetime
df = df[df['A'].apply(lambda v: isinstance(v, datetime))] 
df = df[df['B'].apply(lambda v: isinstance(v, datetime))] 

但是,我要做的是减去A和B的时间。只有时间,而不是日期。

例如,当我执行 df['A']-df['B'] 时,我只希望第一行的输出为 02:46。另外,如何将其转换为分钟,但作为整数?

【问题讨论】:

标签: python pandas


【解决方案1】:

一种解决方法是将日期减去每个日期时间,以确保您只是比较时间,然后减去:

(df.A - df.A.dt.floor('d')) - (df.B - df.B.dt.floor('d'))

0   -1 days +21:14:00
1   -1 days +22:52:00
2   -1 days +20:54:00
3   -1 days +21:56:00
dtype: timedelta64[ns]

【讨论】:

    【解决方案2】:

    你可以这样做:

    pd.to_timedelta(df[['A', 'B']].astype('datetime64').diff(axis=1)['B'].dt.seconds * 10 ** 9)
    
    # 0   02:46:00
    # 1   01:08:00
    # 2   03:06:00
    # 3   02:04:00
    # Name: B, dtype: timedelta64[ns]
    

    这会提取timedelta 对象的seconds 部分,并在考虑nanoseconds 后将其转换回timedelta

    或者,如果您只关心几秒钟:

    pd.to_timedelta(df[['A', 'B']].astype('datetime64').diff(axis=1)['B'].dt.seconds, 's')
    

    为了解释,采取的步骤是:

    1. 处理dtype('O')并转换为datetime64对象
    2. 根据axis=1计算AB的差
    3. 从结果列中提取差异B
    4. 提取timedeltaseconds(删除任何日期、月份等)
    5. seconds 转换回timedelta 对象。

    【讨论】:

      【解决方案3】:

      如果这是您的数据框的形状:

                          A                   B
      0 2017-11-29 17:14:00 2017-11-29 20:00:00
      1 2017-02-15 15:35:00 2017-02-15 16:43:00
      2 2018-10-18 08:02:00 2018-10-18 11:08:00
      3 2017-06-22 09:25:00 2017-06-22 11:29:00
      

      那么您需要做的就是创建一个日期时间对象,然后将您的操作应用于它

      df[['A','B']] = df[['A','B']].apply(pd.to_datetime)
      
      df['B'] - df['A']
      
      0   02:46:00
      1   01:08:00
      2   03:06:00
      3   02:04:00
      dtype: timedelta64[ns]
      

      另一种使用pd.to_timedeltanp.timedelta64 的方法假设两列都已经是日期时间。

         df['diff'] = abs(
          pd.to_timedelta(df["A"].dt.time.astype(str), "h")
          - pd.to_timedelta(df["B"].dt.time.astype(str), "h")
      ) / np.timedelta64(1, "h")
      

      print(df)
                         A                   B      diff
      0 2017-11-29 17:14:00 2017-11-29 20:00:00  2.766667
      1 2017-02-15 15:35:00 2017-02-15 16:43:00  1.133333
      2 2018-10-18 08:02:00 2018-10-18 11:08:00  3.100000
      3 2017-06-22 09:25:00 2017-06-22 11:29:00  2.066667
      

      (
          pd.to_timedelta(df["A"].dt.time.astype(str), "h")
          - pd.to_timedelta(df["B"].dt.time.astype(str), "h")
      ) 
      
      0   -1 days +21:14:00
      1   -1 days +22:52:00
      2   -1 days +20:54:00
      3   -1 days +21:56:00
      dtype: timedelta64[ns]
      

      【讨论】:

      • 这很棘手,因为在您的示例中 B > A,但尝试 A - B 会得到错误的输出。
      • 另外,OP 只想减去时间。如果日期不同,您的回答也会减去日期。
      • 你说得对,让我编辑@Erfan r.ook
      • 非常感谢!有效。我只是对某事感到好奇。如果您正在处理数字,或者“timedelta/datetime”,为什么当您执行 astype(str) 时它会起作用?为什么是字符串?
      • @bonaqua 在后台,日期时间只是一个数字,to_datetimeto_timedelta 通过将日期和时间的字符串表示形式转换为数字来工作,因为我们只需要您的时间元素数据,我们提取它,确保它是字符串而不是日期时间对象,并将其转换为时间增量。然后,我们会根据您的要求进行数学运算。
      【解决方案4】:

      减去A和B的时间。只有时间,没有日期。

      >>> a
      0   2017-11-29 17:14:00
      1   2017-02-15 15:35:00
      2   2018-10-18 08:02:00
      3   2017-06-22 09:25:00
      dtype: datetime64[ns]
      >>> b
      0   2017-11-29 20:00:00
      1   2017-02-15 16:43:00
      2   2018-10-18 11:08:00
      3   2017-06-22 11:29:00
      dtype: datetime64[ns]
      

      减去自午夜以来的秒数

      >>> a1 = (a.dt.hour * 3600) + (a.dt.minute * 60) + (a.dt.microsecond / 1000000)
      >>> b1 = (b.dt.hour * 3600) + (b.dt.minute * 60) + (b.dt.microsecond / 1000000)
      >>> b1-a1
      0     9960.0
      1     4080.0
      2    11160.0
      3     7440.0
      dtype: float64
      

      转换为timedelta

      >>> pd.to_timedelta(b1-a1, unit='S')
      0   02:46:00
      1   01:08:00
      2   03:06:00
      3   02:04:00
      dtype: timedelta64[ns]
      >>> 
      

      .dt accessor


      >>> a2 = pd.DataFrame({'hr':a.dt.hour,'min':a.dt.minute,'microsec':a.dt.microsecond})
      >>> b2 = pd.DataFrame({'hr':b.dt.hour,'min':b.dt.minute,'microsec':b.dt.microsecond})
      >>> b2-a2
         hr  min  microsec
      0   3  -14         0
      1   1    8         0
      2   3    6         0
      3   2    4         0
      >>> c = b2-a2
      >>> pd.to_timedelta(c['hr'],'hours') + pd.to_timedelta(c['min'],'minutes') + pd.to_timedelta(c['microsec'],'microseconds')
      0   02:46:00
      1   01:08:00
      2   03:06:00
      3   02:04:00
      dtype: timedelta64[ns]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-12-01
        • 2016-02-23
        • 2021-12-28
        • 2020-11-21
        • 1970-01-01
        • 2012-05-05
        • 2020-03-19
        • 1970-01-01
        相关资源
        最近更新 更多