Skip to content

解析

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: 時間表現、内部的には午前 0 時からの経過ナノ秒数で表現されます。

ファイルからの日付解析

CSV ファイルからデータを読み込む際、try_parse_dates フラグを True に設定すると、Polars は日付と時刻の解析を試みます。

read_csv

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

CsvReader · Available on feature csv

let df = CsvReader::from_path("docs/data/apple_stock.csv")
    .unwrap()
    .with_try_parse_dates(true)
    .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 │
└────────────┴────────┘

一方、Parquet のようなバイナリ形式は、Polars によって尊重されるスキーマを持っています。

文字列を日付に変換する

文字列でエンコードされた日時のカラムを、日時型に変換することもできます。これを行うには、文字列の str.to_date メソッドを呼び出し、日付文字列のフォーマットを渡します:

read_csv · str.to_date

df = pl.read_csv("docs/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 · Available on feature csv · Available on feature dtype-date

let df = CsvReader::from_path("docs/data/apple_stock.csv")
    .unwrap()
    .with_try_parse_dates(false)
    .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 · Available on feature 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 · Available on feature dtype-datetime · Available on feature timezones

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".to_string()),
            ..Default::default()
        },
        lit("raise"),
    )
    .dt()
    .convert_time_zone("Europe/Brussels".to_string());
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
]