【问题标题】:How can I make Pandas convert a column which contains NaT from timedelta to datetime?如何让 Pandas 将包含 NaT 的列从 timedelta 转换为 datetime?
【发布时间】:2020-09-05 09:17:11
【问题描述】:

我有一个带有 timedelta64[ns] 类型列的 pandas 数据框,我想将其转换为 datetime64[ns]

pd.to_datetime() 函数声称可以做到这一点,并且过去有效,但现在似乎失败了。我认为这可能与我没有注意到的 API 怪癖有关。目前它失败了:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.7/site-packages/pandas/core/tools/datetimes.py", line 724, in to_datetime
    cache_array = _maybe_cache(arg, format, cache, convert_listlike)
  File "/usr/lib/python3.7/site-packages/pandas/core/tools/datetimes.py", line 152, in _maybe_cache
    cache_dates = convert_listlike(unique_dates, format)
  File "/usr/lib/python3.7/site-packages/pandas/core/tools/datetimes.py", line 363, in _convert_listlike_datetimes
    arg, _ = maybe_convert_dtype(arg, copy=False)
  File "/usr/lib/python3.7/site-packages/pandas/core/arrays/datetimes.py", line 1916, in maybe_convert_dtype
    raise TypeError(f"dtype {data.dtype} cannot be converted to datetime64[ns]")
TypeError: dtype timedelta64[ns] cannot be converted to datetime64[ns]

要尝试复制,请使用下面的 MWE:

wget https://chymera.eu/ppb/61ebad.csv
python
import pandas as pd
df = pd.read_csv('61ebad.csv')
df['Animal_death_date'] = pd.to_timedelta(df['Animal_death_date'], errors='coerce')
df['Animal_death_date'] = pd.to_datetime(df['Animal_death_date'], errors='coerce')

如果我使用errors='ignore',也会出现该错误。 作为参考,我使用的是 Pandas 1.0.1

【问题讨论】:

  • 不确定这里的逻辑是什么,您需要如何将 timedelta 转换为 datetime?添加一些由日期时间填充的列?或者添加一些标量,例如 df['Animal_death_date'] = pd.to_timedelta(df['Animal_death_date'], errors='coerce') + pd.to_datetime('2000-01-01') ?

标签: python pandas datetime timedelta


【解决方案1】:

从一个小的更正开始:您有问题的来源列也是 text 列,但仅格式化timedelta

要转换 Animal_death_date 列,请定义以下函数:

def myDateConv(tt):
    return pd.to_datetime('2020-' + tt, format='%Y-%j days %X.%f')\
        if len(tt) > 0 else np.nan

我假设您的日期是从今年开始的,因此 2020 作为初始日期 整个日期字符串的一部分。如果他们来自其他年份,请更改此 相应的前缀。

但早在您阅读源文件时应用此功能:

df = pd.read_csv('61ebad.csv', index_col=0, parse_dates=['Treatment_start_date',
    'Treatment_end_date', 'FMRIMeasurement_date', 'OpenFieldTestMeasurement_date',
    'ForcedSwimTestMeasurement_date', 'CageStay_start_date', 'Cage_Treatment_start_date',
    'Cage_Treatment_end_date', 'SucrosePreferenceMeasurement_date', 'reference_date'],
    converters = { 'Animal_death_date': myDateConv })

注意附加参数:

  • index_col - 将初始列视为索引,
  • parse_dates - 将“正常”格式的日期转换为日期时间
  • converters - 将上述函数应用到源 Animal_death_date 列。

我认为,这种解决方案比单独转换更简单,更易读 特定列。

【讨论】:

    【解决方案2】:

    如果需要将时间增量转换为日期时间,添加一些开始日期时间:

    import pandas as pd
    
    df = pd.read_csv('https://chymera.eu/ppb/61ebad.csv')
    start = pd.to_datetime('2000-01-01')
    df['Animal_death_date'] = pd.to_timedelta(df['Animal_death_date'], errors='coerce') + start
    print (df['Animal_death_date'] )
    0                     NaT
    1                     NaT
    2                     NaT
    3                     NaT
    4                     NaT
    
    843                   NaT
    844                   NaT
    845   2000-05-12 19:00:00
    846   2000-05-12 19:00:00
    847   2000-05-12 19:00:00
    Name: Animal_death_date, Length: 848, dtype: datetime64[ns]
    

    或者添加一些由日期时间填充的列:

    import pandas as pd
    
    df = pd.read_csv('https://chymera.eu/ppb/61ebad.csv')
    start = pd.to_datetime(df['FMRIMeasurement_date'])
    df['Animal_death_date'] = pd.to_timedelta(df['Animal_death_date'], errors='coerce') + start
    print (df['Animal_death_date'] )
    0                     NaT
    1                     NaT
    2                     NaT
    3                     NaT
    4                     NaT
    
    843                   NaT
    844                   NaT
    845   2018-10-04 19:20:54
    846   2018-10-04 19:20:54
    847   2018-10-04 19:20:54
    Name: Animal_death_date, Length: 848, dtype: datetime64[ns]
    

    【讨论】:

    • 谢谢!实际上我想我还记得发生了什么,即 .to_datetime() 用于自动生成相对于 1970-01-01 的日期时间。
    • @TheChymera - 是的,我认为新版本的 pandas 改变了这种行为。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2018-05-19
    • 2015-01-02
    相关资源
    最近更新 更多