【问题标题】:pandas error creating TimeDeltas from Datetime operationpandas 从 Datetime 操作创建 TimeDeltas 时出错
【发布时间】:2015-11-15 05:19:51
【问题描述】:

我查看了其他几个相关的问题hereherehere,但没有一个和我遇到过完全相同的问题。

我使用的是 Pandas 0.16.2 版。我在 Pandas 数据框中有几列,数据类型为 datetime64[ns]:

In [6]: date_list = ["SubmittedDate","PolicyStartDate", "PaidUpDate", "MaturityDate", "DraftDate", "CurrentValuationDate", "DOB", "InForceDate"]

In [11]: data[date_list].head()

Out[11]:
      SubmittedDate PolicyStartDate PaidUpDate MaturityDate DraftDate  \
    0           NaT      2002-11-18        NaT   2041-03-04       NaT
    1           NaT      2015-01-13        NaT          NaT       NaT
    2           NaT      2014-10-15        NaT          NaT       NaT
    3           NaT      2009-08-27        NaT          NaT       NaT
    4           NaT      2007-04-19        NaT   2013-10-01       NaT

      CurrentValuationDate        DOB InForceDate
    0           2015-04-30 1976-03-04  2002-11-18
    1                  NaT 1949-09-27  2015-01-13
    2                  NaT 1947-06-15  2014-10-15
    3           2015-07-30 1960-06-07  2009-08-27
    4           2010-04-21 1950-10-01  2007-04-19

这些最初是字符串格式(例如“1976-03-04”),我使用以下方法将其转换为日期时间对象:

In [7]: for datecol in date_list:
   ...:         data[datecol] = pd.to_datetime(data[datecol], coerce=True, errors = 'raise')

以下是每一列的数据类型:

In [8]: for datecol in date_list:
              print data[datecol].dtypes

返回:

datetime64[ns]
datetime64[ns]
datetime64[ns]
datetime64[ns]
datetime64[ns]
datetime64[ns]
datetime64[ns]
datetime64[ns]

到目前为止,一切都很好。但我想要做的是为这些列中的每一个创建一个新列,给出从某个日期开始的天数(作为整数)。

In [13]: current_date = pd.to_datetime("2015-07-31")

我第一次运行这个:

In [14]: for i in date_list:
   ....:         data[i+"InDays"] = data[i].apply(lambda x: current_date - x)

但是,当我检查返回列的 dtype 时:

In [15]: for datecol in date_list:
   ....:         print data[datecol + "InDays"].dtypes

我得到了这些:

object
timedelta64[ns]
object
timedelta64[ns]
object
timedelta64[ns]
timedelta64[ns]
timedelta64[ns]

我不知道为什么其中三个是对象,什么时候应该是时间增量。我接下来要做的是:

In [16]: for i in date_list:
   ....:         data[i+"InDays"] = data[i+"InDays"].dt.days

这种方法适用于 timedelta 列。但是,由于其中三列不是 timedeltas,我收到此错误:

AttributeError: Can only use .dt accessor with datetimelike values

我怀疑这三列中的某些值会阻止 Pandas 将它们转换为 timedeltas。我不知道如何计算出这些值可能是什么。

【问题讨论】:

    标签: python datetime numpy pandas timedelta


    【解决方案1】:

    出现问题是因为您有三列只有 NaT 值,这会导致在您对其应用条件时将这些列视为对象。

    您应该在apply 部分中添加某种条件,以在NaT 的情况下默认为某个时间增量。示例 -

    for i in date_list:
        data[i+"InDays"] = data[i].apply(lambda x: current_date - x if x is not pd.NaT else pd.Timedelta(0))
    

    或者如果你不能做到以上,你应该在你想做的地方加上一个条件 - data[i+"InDays"] = data[i+"InDays"].dt.days ,只有在该系列的dtype 允许的情况下才接受它。

    或者更简单的方法是更改​​apply 部分以直接获取您想要的内容 -

    for i in date_list:
        data[i+"InDays"] = data[i].apply(lambda x: (current_date - x).days if x is not pd.NaT else x)
    

    这将输出 -

    In [110]: data
    Out[110]:
      SubmittedDate PolicyStartDate PaidUpDate MaturityDate DraftDate  \
    0           NaT      2002-11-18        NaT   2041-03-04       NaT
    1           NaT      2015-01-13        NaT          NaT       NaT
    2           NaT      2014-10-15        NaT          NaT       NaT
    3           NaT      2009-08-27        NaT          NaT       NaT
    4           NaT      2007-04-19        NaT   2013-10-01       NaT
    
      CurrentValuationDate        DOB InForceDate SubmittedDateInDays  \
    0           2015-04-30 1976-03-04  2002-11-18                 NaT
    1                  NaT 1949-09-27  2015-01-13                 NaT
    2                  NaT 1947-06-15  2014-10-15                 NaT
    3           2015-07-30 1960-06-07  2009-08-27                 NaT
    4           2010-04-21 1950-10-01  2007-04-19                 NaT
    
       PolicyStartDateInDays PaidUpDateInDays MaturityDateInDays DraftDateInDays  \
    0                   4638              NaT              -9348             NaT
    1                    199              NaT                NaN             NaT
    2                    289              NaT                NaN             NaT
    3                   2164              NaT                NaN             NaT
    4                   3025              NaT                668             NaT
    
      CurrentValuationDateInDays  DOBInDays  InForceDateInDays
    0                         92      14393               4638
    1                        NaN      24048                199
    2                        NaN      24883                289
    3                          1      20142               2164
    4                       1927      23679               3025
    

    如果您希望将您的 NaT 更改为 NaN,您可以使用 -

    for i in date_list:
        data[i+"InDays"] = data[i].apply(lambda x: (current_date - x).days if x is not pd.NaT else np.NaN)
    

    示例/演示 -

    In [114]: for i in date_list:
       .....:     data[i+"InDays"] = data[i].apply(lambda x: (current_date - x).days if x is not pd.NaT else np.NaN)
       .....:
    
    In [115]: data
    Out[115]:
      SubmittedDate PolicyStartDate PaidUpDate MaturityDate DraftDate  \
    0           NaT      2002-11-18        NaT   2041-03-04       NaT
    1           NaT      2015-01-13        NaT          NaT       NaT
    2           NaT      2014-10-15        NaT          NaT       NaT
    3           NaT      2009-08-27        NaT          NaT       NaT
    4           NaT      2007-04-19        NaT   2013-10-01       NaT
    
      CurrentValuationDate        DOB InForceDate  SubmittedDateInDays  \
    0           2015-04-30 1976-03-04  2002-11-18                  NaN
    1                  NaT 1949-09-27  2015-01-13                  NaN
    2                  NaT 1947-06-15  2014-10-15                  NaN
    3           2015-07-30 1960-06-07  2009-08-27                  NaN
    4           2010-04-21 1950-10-01  2007-04-19                  NaN
    
       PolicyStartDateInDays  PaidUpDateInDays  MaturityDateInDays  \
    0                   4638               NaN               -9348
    1                    199               NaN                 NaN
    2                    289               NaN                 NaN
    3                   2164               NaN                 NaN
    4                   3025               NaN                 668
    
       DraftDateInDays  CurrentValuationDateInDays  DOBInDays  InForceDateInDays
    0              NaN                          92      14393               4638
    1              NaN                         NaN      24048                199
    2              NaN                         NaN      24883                289
    3              NaN                           1      20142               2164
    4              NaN                        1927      23679               3025
    

    【讨论】:

    • 谢谢,但这三列并非只有 NaT 值;我展示的 data[date_list].head() 中没有任何内容。另外,我不想将 NaT 转换为 Timedelta(0),我只想忽略它们。我尝试使用以下更改运行您的代码: for i in date_list: data[i+"InDays"] = data[i].apply(lambda x: current_date - x if x is not pd.NaT else pd.NaT) 但输出列仍然是对象
    • 不,仍然无法正常工作。这三列的输出中包含 NaN 而不是 NaT。就像 Pandas 之后对那些将它们变成对象的列做了一些事情。
    • 检查最新的更新,如果这仍然不起作用,请告诉我,或者您实际上需要 TimeDelta() 中的数据用于其他计算。
    • 很高兴能为您提供帮助。
    猜你喜欢
    • 2013-05-10
    • 2015-02-04
    • 1970-01-01
    • 2019-12-01
    • 2019-04-22
    • 1970-01-01
    • 1970-01-01
    • 2018-09-06
    • 1970-01-01
    相关资源
    最近更新 更多