跳到内容

解析

Polars 原生支持解析时间序列数据,并能执行更复杂的运算,例如时间分组和重采样。

数据类型

Polars 具有以下日期时间数据类型

  • Date:日期表示,例如 2014-07-08。它在内部表示为自 Unix 纪元以来的天数,由一个 32 位有符号整数编码。
  • Datetime:日期时间表示,例如 2014-07-08 07:00:00。它在内部表示为自 Unix 纪元以来的 64 位整数,并可以有不同的单位,例如纳秒 (ns)、微秒 (us)、毫秒 (ms)。
  • Duration:一种时间差类型,通过 Date/Datetime 相减创建。类似于 Python 中的 timedelta
  • Time:时间表示,在内部表示为自午夜以来的纳秒。

从文件解析日期

从 CSV 文件加载时,如果 `try_parse_dates` 标志设置为 `True`,Polars 会尝试解析日期和时间。

read_csv

df = pl.read_csv("docs/assets/data/apple_stock.csv", try_parse_dates=True)
print(df)

CsvReader · 在功能 csv 中可用

let df = CsvReadOptions::default()
    .map_parse_options(|parse_options| parse_options.with_try_parse_dates(true))
    .try_into_reader_with_file_path(Some("docs/assets/data/apple_stock.csv".into()))
    .unwrap()
    .finish()
    .unwrap();
println!("{}", &df);

shape: (100, 2)
┌────────────┬────────┐
│ Date       ┆ Close  │
│ ---        ┆ ---    │
│ date       ┆ f64    │
╞════════════╪════════╡
│ 1981-02-23 ┆ 24.62  │
│ 1981-05-06 ┆ 27.38  │
│ 1981-05-18 ┆ 28.0   │
│ 1981-09-25 ┆ 14.25  │
│ 1982-07-08 ┆ 11.0   │
│ …          ┆ …      │
│ 2012-05-16 ┆ 546.08 │
│ 2012-12-04 ┆ 575.85 │
│ 2013-07-05 ┆ 417.42 │
│ 2013-11-07 ┆ 512.49 │
│ 2014-02-25 ┆ 522.06 │
└────────────┴────────┘

此标志将根据 `infer_schema_length` 设置(默认为 100 行)对多行数据触发 Schema 推断。Schema 推断计算成本高昂,如果使用大量行,可能会减慢文件加载速度。

另一方面,parquet 等二进制格式具有 Polars 所遵循的 Schema。

将字符串转换为日期

您还可以将编码为字符串的日期时间列转换为日期时间类型。您可以通过调用字符串 `str.to_date` 方法并传入日期字符串的格式来完成此操作。

read_csv · str.to_date

df = pl.read_csv("docs/assets/data/apple_stock.csv", try_parse_dates=False)

df = df.with_columns(pl.col("Date").str.to_date("%Y-%m-%d"))
print(df)

CsvReader · str.replace_all · 在功能 csv 中可用 · 在功能 dtype-date 中可用

let df = CsvReadOptions::default()
    .map_parse_options(|parse_options| parse_options.with_try_parse_dates(false))
    .try_into_reader_with_file_path(Some("docs/assets/data/apple_stock.csv".into()))
    .unwrap()
    .finish()
    .unwrap();
let df = df
    .clone()
    .lazy()
    .with_columns([col("Date").str().to_date(StrptimeOptions::default())])
    .collect()?;
println!("{}", &df);

shape: (100, 2)
┌────────────┬────────┐
│ Date       ┆ Close  │
│ ---        ┆ ---    │
│ date       ┆ f64    │
╞════════════╪════════╡
│ 1981-02-23 ┆ 24.62  │
│ 1981-05-06 ┆ 27.38  │
│ 1981-05-18 ┆ 28.0   │
│ 1981-09-25 ┆ 14.25  │
│ 1982-07-08 ┆ 11.0   │
│ …          ┆ …      │
│ 2012-05-16 ┆ 546.08 │
│ 2012-12-04 ┆ 575.85 │
│ 2013-07-05 ┆ 417.42 │
│ 2013-11-07 ┆ 512.49 │
│ 2014-02-25 ┆ 522.06 │
└────────────┴────────┘

格式字符串规范可在此处找到。.

从日期列提取日期特征

您可以使用 `.dt` 命名空间从日期列中提取年份或日期等数据特征。

dt.year

df_with_year = df.with_columns(pl.col("Date").dt.year().alias("year"))
print(df_with_year)

dt.year

let df_with_year = df
    .clone()
    .lazy()
    .with_columns([col("Date").dt().year().alias("year")])
    .collect()?;
println!("{}", &df_with_year);

shape: (100, 3)
┌────────────┬────────┬──────┐
│ Date       ┆ Close  ┆ year │
│ ---        ┆ ---    ┆ ---  │
│ date       ┆ f64    ┆ i32  │
╞════════════╪════════╪══════╡
│ 1981-02-23 ┆ 24.62  ┆ 1981 │
│ 1981-05-06 ┆ 27.38  ┆ 1981 │
│ 1981-05-18 ┆ 28.0   ┆ 1981 │
│ 1981-09-25 ┆ 14.25  ┆ 1981 │
│ 1982-07-08 ┆ 11.0   ┆ 1982 │
│ …          ┆ …      ┆ …    │
│ 2012-05-16 ┆ 546.08 ┆ 2012 │
│ 2012-12-04 ┆ 575.85 ┆ 2012 │
│ 2013-07-05 ┆ 417.42 ┆ 2013 │
│ 2013-11-07 ┆ 512.49 ┆ 2013 │
│ 2014-02-25 ┆ 522.06 ┆ 2014 │
└────────────┴────────┴──────┘

混合偏移

如果您有混合偏移(例如,由于跨越夏令时),则可以使用 `utc=True`,然后转换为您的时区。

str.to_datetime · dt.convert_time_zone · 在功能 timezone 中可用

data = [
    "2021-03-27T00:00:00+0100",
    "2021-03-28T00:00:00+0100",
    "2021-03-29T00:00:00+0200",
    "2021-03-30T00:00:00+0200",
]
mixed_parsed = (
    pl.Series(data)
    .str.to_datetime("%Y-%m-%dT%H:%M:%S%z")
    .dt.convert_time_zone("Europe/Brussels")
)
print(mixed_parsed)

str.replace_all · dt.convert_time_zone · 在功能 timezones 中可用 · 在功能 dtype-datetime 中可用

let data = [
    "2021-03-27T00:00:00+0100",
    "2021-03-28T00:00:00+0100",
    "2021-03-29T00:00:00+0200",
    "2021-03-30T00:00:00+0200",
];
let q = col("date")
    .str()
    .to_datetime(
        Some(TimeUnit::Microseconds),
        None,
        StrptimeOptions {
            format: Some("%Y-%m-%dT%H:%M:%S%z".into()),
            ..Default::default()
        },
        lit("raise"),
    )
    .dt()
    .convert_time_zone(
        TimeZone::opt_try_new(Some("Europe/Brussels"))
            .unwrap()
            .unwrap(),
    );
let mixed_parsed = df!("date" => &data)?.lazy().select([q]).collect()?;

println!("{}", &mixed_parsed);

shape: (4,)
Series: '' [datetime[μs, Europe/Brussels]]
[
    2021-03-27 00:00:00 CET
    2021-03-28 00:00:00 CET
    2021-03-29 00:00:00 CEST
    2021-03-30 00:00:00 CEST
]