使用Polars轻松将字符串列转换为pl.datetime

15
考虑一个 Polars 数据框,其中一列是str类型,表示日期格式为'27 July 2020'。我想将这一列转换为polars.datetime类型,该类型与Python标准库中的datetime不同。下面的代码使用标准的datetime格式可以工作,但是Polars不能将该列中的值识别为日期。
import polars as pl
from datetime import datetime

df = pd.read_csv('<some CSV file containing a column called 'event_date'>')
df = df.with_columns([   
        pl.col('event_date').apply(lambda x: x.replace(" ","-"))\
                            .apply(lambda x: datetime.strptime(x, '%d-%B-%Y'))
])


假设我们尝试进一步处理 df,以创建一个新列,指示事件发生的年度季度。
df = df.with_columns([
        pl.col('event_date').apply(lambda x: x.month)\
                            .apply(lambda x: 1 if x in range(1,4) else 2 if x in range(4,7) else 3 if x in range(7,10) else 4)\
                            .alias('quarter')
])

代码返回以下错误,因为它将 event_type 定义为 dtype Object("object") 而不是 datetimepolars.datetime
thread '<unnamed>' panicked at 'dtype Object("object") not supported', src/series.rs:992:24
--- PyO3 is resuming a panic after fetching a PanicException from Python. ---
PanicException: Unwrapped panic from Python code
1个回答

33

更新:从polars v0.17.10开始,可以使用.str.to_datetime()

df = pl.from_repr("""
┌─────┬──────────────────┐
│ id  ┆ event_date       │
│ --- ┆ ---              │
│ i64 ┆ str              │
╞═════╪══════════════════╡
│ 1   ┆ 27 July 2020     │
│ 2   ┆ 31 December 2020 │
└─────┴──────────────────┘
""")

df.with_columns(
   pl.col("event_date").str.to_datetime("%d %B %Y")
)

shape: (2, 2)
┌─────┬─────────────────────┐
│ id  ┆ event_date          │
│ --- ┆ ---                 │
│ i64 ┆ datetime[μs]        │
╞═════╪═════════════════════╡
│ 12020-07-27 00:00:00 │
│ 22020-12-31 00:00:00 │
└─────┴─────────────────────┘

将字符串转换为日期/时间的最简单方法是使用 Polars 自己的 strptime 函数(而不是 Python 的 datetime 模块中同名的函数)。

例如,让我们从这个数据开始。

import polars as pl

df = pl.DataFrame({
    'date_str': ["27 July 2020", "31 December 2020"]
})
print(df)

shape: (2, 1)
┌──────────────────┐
│ date_str         │
│ ---              │
│ str              │
╞══════════════════╡
│ 27 July 2020     │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 31 December 2020 │
└──────────────────┘

要进行转换,请使用 Polars 的 strptime 函数。

df.with_columns(pl.col('date_str').str.strptime(pl.Date, fmt='%d %B %Y').cast(pl.Datetime))

shape: (2, 1)
┌─────────────────────┐
│ date_str            │
│ ---                 │
│ datetime[μs]        │
╞═════════════════════╡
│ 2020-07-27 00:00:00 │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 2020-12-31 00:00:00 │
└─────────────────────┘

请注意,我们不需要用破折号替换空格。我已将结果转换为Datetime(根据您的问题),但您可能可以使用Date代替。
目前,当返回类型为Python Date / Datetime对象时,apply方法无法正常工作,但是有一个request。 也就是说,最好使用Polars的strptime。 它比调用python datetime代码要快得多。
编辑:截至Polars 0.13.19,apply方法将自动将Python日期/时间转换为Polars日期/时间。

为了让您的数据框反映出更改,请将函数分配给它:df = df.with_colu.... - PeJota
3
在 Polars 的讨论中,你会发现非赋值操作很常见,特别是当我们只想打印结果而不改变原始 DataFrame 时。因此,我们不需要进行赋值操作,而是直接不赋值,这就起到了隐式打印的效果,避免了两行代码的问题。 - user18559875
1
from_repr是纯粹的巫术,谢谢你提出这个问题! - Filippo Vitale

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接