【问题标题】:Pandas `.to_pydatetime()` not working inside a DataFramePandas `.to_pydatetime()` 在 DataFrame 中不起作用
【发布时间】:2020-02-23 21:14:47
【问题描述】:

我有像'03-21-2019' 这样的字符串,我想将其转换为本机Python 日期时间对象:即datetime.datetime 类型。通过pandas,转换很容易:

import pandas as pd
import datetime as dt

date_str = '03-21-2019'
pd_Timestamp = pd.to_datetime(date_str)
py_datetime_object = pd_Timestamp.to_pydatetime()
print(type(py_datetime_object))

结果

<class 'datetime.datetime'>

这正是我想要的,因为我想通过从另一个中减去其中一个来计算 timedelta's - 在本机 Python datetime.datetime 类中完美定义。但是,我的数据在pd.DataFrame 中。当我尝试以下代码时:

import pandas as pd
import datetime as dt

df = pd.DataFrame(columns=['Date'])
df.loc[0] = ['03-21-2019']
df['Date'] = df['Date'].apply(lambda x:
                              pd.to_datetime(x).to_pydatetime())
print(type(df['Date'].iloc[0]))

结果是

<class 'pandas._libs.tslibs.timestamps.Timestamp'>

这是 WRONG 类型,我终其一生都无法弄清楚为什么只有一部分 lambda 表达式被评估(即, string-to-pandas-Timestamp),而不是最后一部分(即 pandas-Timestamp-to-datetime.datetime)。如果我明确定义函数而不是使用 lambda 表达式,它也不起作用:

import pandas as pd
import datetime as dt


def to_native_datetime(date_str: str) -> dt.datetime:
    return pd.to_datetime(date_str).to_pydatetime()


df = pd.DataFrame(columns=['Date'])
df.loc[0] = ['03-21-2019']
df['Date'] = df['Date'].apply(to_native_datetime)
print(type(df['Date'].iloc[0]))

结果和以前一样。它肯定是函数的一部分,因为结果不再是字符串。但我想要原生 Python datetime.datetime 对象,但我看不出有什么办法。这看起来像是pandas 中的一个错误,但我当然愿意将其视为我的用户错误。

为什么我不能从 pandas.DataFrame 字符串列中获取本机 datetime.datetime 对象?

我查看了this threadthis one,但他们都没有回答我的问题。

[编辑]:这里有一些更奇怪的东西:

import pandas as pd
import datetime as dt


def to_native_datetime(date_str: str) -> dt.datetime:
    return dt.datetime.strptime(date_str, '%m-%d-%Y')


df = pd.DataFrame(columns=['Date'])
df.loc[0] = ['03-21-2019']
df['Date'] = df['Date'].apply(to_native_datetime)
print(type(df['Date'].iloc[0]))

这里我什至没有使用pandas 来转换字符串,我STILL得到一个

<class 'pandas._libs.tslibs.timestamps.Timestamp'>

别闹了!

非常感谢您的宝贵时间!

[进一步编辑]:显然,在this thread 中,在 Nehal J Wani 的回答中,当您分配到 pd.DataFrame 时,pandas 会自动转换回其本机日期时间格式。这不是我想听到的,但显然,当我读出pd.DataFrame 时,我将不得不即时转换。

【问题讨论】:

  • 我面临同样的问题。奇怪的是,pandas 对象索引将维护 datetime.datetime 对象,而不是 DataFrame 中的系列或列。

标签: python-3.x pandas python-datetime


【解决方案1】:

根据您的实际目标,您有几个没有直接提及的选项。

1) 如果您有一个静态日期时间对象或一列 (pandas) 时间戳,并且您愿意处理 Pandas 版本的 Timedelta (pandas._libs.tslibs.timedeltas.Timedelta),则可以直接在 pandas 中进行减法:

df = pd.DataFrame(columns=['Date'])
df.loc[0] = [pd.to_datetime('03-21-2019')]
df.loc[:, 'Offset'] = pd.Series([datetime.now()])
df.loc[:, 'Diff1'] = df['Offset'] - df['Date']
df.loc[:, 'Diff2'] = df['Date'] - datetime.now()

2) 如果您不关心 Dataframe,但愿意处理列表/numpy 数组,则可以通过对系列而不是单个元素进行操作来将日期时间转换为 python-native 日期时间。下面,arrnumpy.ndarraydatetime.datetime 对象。您可以使用list(arr) 将其更改为常规日期时间列表:

arr = df['Date'].dt.to_pydatetime()

【讨论】:

    【解决方案2】:

    感谢Sarah Messer 的回答和one,我可以通过将数组重新分配回数据框并将其dtype 强制为对象来解决问题:

    arr_date = df['Date'].dt.to_pydatetime()
    df['Date']= pd.Series(arr_date, dtype=object)
    

    示例:

    import pandas as pd
    from datetime import datetime
    
    df = pd.DataFrame({"date": [datetime(2021, 8, 28, 4, 10), datetime(2021, 8, 28, 4, 10)]})
    df.dtypes
    
    #   date    datetime64[ns]
    #   dtype: object
    
    arr_date = df["date"].dt.to_pydatetime()
    df["date"] = pd.Series(arr_date, dtype="object")
    df.dtypes
    
    #   date    object
    #   dtype: object
    
    df.iloc[0,0]
    
    # datetime.datetime(2021, 8, 28, 4, 10)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-02
      • 2016-12-04
      • 2020-09-03
      • 1970-01-01
      • 2019-12-02
      • 2019-11-14
      相关资源
      最近更新 更多