创建

series


#![allow(unused)]
fn main() {
// 从 Vec, 切片和数组, series 可以携带名称
let s = Series::new("from vec", vec![1, 2, 3]);
let s = Series::new("from slice", &[true, false, true]);
let s = Series::new("from array", ["rookie", "long", "lin"]);
}

dataframe

空 dataframe


#![allow(unused)]
fn main() {
let df = DataFrame::default();
assert!(df.is_empty());
}

从多个 Vec<Series> 创建


#![allow(unused)]
fn main() {
let s1 = Series::new("Fruit", &["Apple", "Apple", "Pear"]);
let s2 = Series::new("Color", &["Red", "Yellow", "Green"]);

let df: Result<DataFrame> = DataFrame::new(vec![s1, s2]);
}

使用 df! 宏, 注意, 返回类型为Result<DataFrame>


#![allow(unused)]
fn main() {
let df: Result<DataFrame> = df!("Fruit" => &["Apple", "Apple", "Pear"],
                                "Color" => &["Red", "Yellow", "Green"]);
}

查看数据

查看头和尾, 与 pandas 中同名函数类似, head, tail


#![allow(unused)]
fn main() {
let countries: DataFrame =
    df!(
        "Rank by GDP (2021)" => &[1, 2, 3, 4, 5],
        "Continent" => &["North America", "Asia", "Asia", "Europe", "Europe"],
        "Country" => &["United States", "China", "Japan", "Germany", "United Kingdom"],
        "Capital" => &["Washington", "Beijing", "Tokyo", "Berlin", "London"]
    )?;
assert_eq!(countries.shape(), (5, 4));

println!("{}", countries.head(Some(3)));
}
output
shape: (3, 4)
┌────────────────────┬───────────────┬───────────────┬────────────┐
│ Rank by GDP (2021) ┆ Continent     ┆ Country       ┆ Capital    │
│ ---                ┆ ---           ┆ ---           ┆ ---        │
│ i32                ┆ str           ┆ str           ┆ str        │
╞════════════════════╪═══════════════╪═══════════════╪════════════╡
│ 1                  ┆ North America ┆ United States ┆ Washington │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 2                  ┆ Asia          ┆ China         ┆ Beijing    │
├╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌┤
│ 3                  ┆ Asia          ┆ Japan         ┆ Tokyo      │
└────────────────────┴───────────────┴───────────────┴────────────┘

#![allow(unused)]
fn main() {
let countries: DataFrame =
    df!("Rank (2021)" => &[105, 106, 107, 108, 109],
        "Apple Price (€/kg)" => &[0.75, 0.70, 0.70, 0.65, 0.52],
        "Country" => &["Kosovo", "Moldova", "North Macedonia", "Syria", "Turkey"])?;
assert_eq!(countries.shape(), (5, 3));

println!("{}", countries.tail(Some(2)));
}
Output
shape: (2, 3)
┌─────────────┬────────────────────┬─────────┐
│ Rank (2021) ┆ Apple Price (€/kg) ┆ Country │
│ ---         ┆ ---                ┆ ---     │
│ i32         ┆ f64                ┆ str     │
╞═════════════╪════════════════════╪═════════╡
│ 108         ┆ 0.65               ┆ Syria   │
├╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌┤
│ 109         ┆ 0.52               ┆ Turkey  │
└─────────────┴────────────────────┴─────────┘

获取列名


#![allow(unused)]
fn main() {
let df: DataFrame = df!("Language" => &["Rust", "Python"],
                        "Designer" => &["Graydon Hoare", "Guido van Rossum"])?;

assert_eq!(df.get_column_names(), &["Language", "Designer"]);
}

如果要获取列值, 可以使用 column columns

统计汇总方法

polars DataFrame 没有提供 describe 这样的快速统计方法, 但调用 mean, std 等方法也非常简单便捷

count

对于整个 DataFrame 可以调用 shape 获取 DataFrame 形状, 如果想获取某个列经操作变形后个数, 可以使用 count


#![allow(unused)]
fn main() {
let df1: DataFrame = df!("D1" => &[1, 3, 1, 5, 6],
                     "D2" => &[3, 2, 3, 5, 3])?;
let df2 = df1
    .lazy()
    .select(&[
        col("D1").count().alias("total"),
        col("D1").filter(col("D1").gt(lit(3))).count().alias("D1 > 3"),
    ])
    .collect()
    .unwrap();
println!("{}", df2);
}
Output
shape: (1, 2)
┌───────┬────────┐
│ total ┆ D1 > 3 │
│ ---   ┆ ---    │
│ u32   ┆ u32    │
╞═══════╪════════╡
│ 5     ┆ 2      │
└───────┴────────┘

mean

DataFrame mean

Expr mean

如果要计算滑动平均等带时间窗口数据, 请查看 rolling_mean

其他方法

其他统计学方法名称与 pandas 中同名或类似

转置

transpose 可转置 DataFrame, 这个操作消耗大量性能


#![allow(unused)]
fn main() {
let df1: DataFrame = df!("D1" => &[1, 3, 1, 5, 6],
                         "D2" => &[3, 2, 3, 5, 3])?;
println!("{}", df1.transpose()?);
}
Output
shape: (2, 5)
┌──────────┬──────────┬──────────┬──────────┬──────────┐
│ column_0 ┆ column_1 ┆ column_2 ┆ column_3 ┆ column_4 │
│ ---      ┆ ---      ┆ ---      ┆ ---      ┆ ---      │
│ i32      ┆ i32      ┆ i32      ┆ i32      ┆ i32      │
╞══════════╪══════════╪══════════╪══════════╪══════════╡
│ 1        ┆ 3        ┆ 1        ┆ 5        ┆ 6        │
├╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┼╌╌╌╌╌╌╌╌╌╌┤
│ 3        ┆ 2        ┆ 3        ┆ 5        ┆ 3        │
└──────────┴──────────┴──────────┴──────────┴──────────┘

排序

sort


#![allow(unused)]
fn main() {
let df1: DataFrame = df!("D1" => &[1, 3, 1, 5, 6],
                         "D2" => &[3, 2, 3, 5, 3])?;
println!("{}", df1.sort(["D1"], vec![true])?);
}
Output
shape: (5, 2)
┌─────┬─────┐
│ D1  ┆ D2  │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 6   ┆ 3   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 5   ┆ 5   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 1   ┆ 3   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 1   ┆ 3   │
└─────┴─────┘

查询&更新数据

获取一个或多个列

column columns

这些函数返回一个或多个 Series.

在 select context 里, 可以用col 构建一个列选择表达式, 接着对其进行操作.

polars DataFrame 实现了 Index trait, 所以你也可以通过以下方式获取列, 请注意, pandas 中这种方式拿到的是 slice.


#![allow(unused)]
fn main() {
let df1: DataFrame = df!("D1" => &[1, 3, 1, 5, 6],
                         "D2" => &[3, 2, 3, 5, 3])?;
println!("{}", df1[1]);
println!("{}", df1["D1"]);
}
Output
shape: (5,)
Series: 'D2' [i32]
[
        3
        2
        3
        5
        3
]
shape: (5,)
Series: 'D1' [i32]
[
        1
        3
        1
        5
        6
]

获取切片

slice


#![allow(unused)]
fn main() {
let df1: DataFrame = df!("D1" => &[1, 3, 1, 5, 6],
                     "D2" => &[3, 2, 3, 5, 3])?;
println!("{}", df1.slice(2, 3));
}

如果要获取子区域, 可以使用 select + columns


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 3, 1, 5, 6],
    "D2" => &[3, 2, 3, 5, 3],
    "D3" => &[9, 7, 5, 2, 4]
)?;
let df2 = df1
    .lazy()
    .select([cols(["D1", "D3"]).slice(2, 3)])
    .collect()?;
println!("{}", df2);
}
Output
shape: (3, 2)
┌─────┬─────┐
│ D1  ┆ D3  │
│ --- ┆ --- │
│ i32 ┆ i32 │
╞═════╪═════╡
│ 1   ┆ 5   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 4   │
└─────┴─────┘

获取某个标量


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 3, 1, 5, 6],
    "D2" => &[3, 2, 3, 5, 3],
    "D3" => &[9, 7, 5, 2, 4]
)?;
println!("{}", df1["D1"].get(0));
}
Output
1

布尔索引

polars 中没有布尔索引, 但可以通过 filter 达到相同效果


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 3, 1, 5, 6],
    "D2" => &[3, 2, 3, 5, 3],
    "D3" => &[9, 7, 5, 2, 4]
)?;
let df2 = df1.lazy().filter(col("D1").gt(3)).collect()?;
println!("{}", df2);
}
Output
shape: (2, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 5   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘

添加新列

通过 lazy frame 的 with_column 可以方便地根据已有列添加新列


#![allow(unused)]
fn main() {
  let df1: DataFrame = df!(
      "D1" => &[1, 3, 1, 5, 6],
      "D2" => &[3, 2, 3, 5, 3],
      "D3" => &[9, 7, 5, 2, 4]
  )?;
  let df2 = df1
      .lazy()
      .with_column(
          when(col("D1").gt(3))
              .then(lit(true))
              .otherwise(lit(false))
              .alias("D1 > 3"),
      )
      .collect()?;
  println!("{}", df2);
}
Output
shape: (5, 4)
┌─────┬─────┬─────┬────────┐
│ D1  ┆ D2  ┆ D3  ┆ D1 > 3 │
│ --- ┆ --- ┆ --- ┆ ---    │
│ i32 ┆ i32 ┆ i32 ┆ bool   │
╞═════╪═════╪═════╪════════╡
│ 1   ┆ 3   ┆ 9   ┆ false  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 3   ┆ 2   ┆ 7   ┆ false  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 1   ┆ 3   ┆ 5   ┆ false  │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 5   ┆ 5   ┆ 2   ┆ true   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   ┆ true   │
└─────┴─────┴─────┴────────┘

修改数据

DataFrame 可以通过 replace + set_at_idx 实现


#![allow(unused)]
fn main() {
let mut df1: DataFrame = df!(
    "D1" => &[1, 3, 1, 5, 6],
    "D2" => &[3, 2, 3, 5, 3],
    "D3" => &[9, 7, 5, 2, 4]
)?;
let new_d1 = df1["D1"]
    .i32()
    .and_then(|s| s.set_at_idx(vec![0], Some(100)))?;
let df2 = df1.replace("D1", new_d1)?;
println!("{}", df2);
}
Output
shape: (5, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 100 ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 1   ┆ 3   ┆ 5   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 5   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘

缺失值处理

在 polars 里缺失值使用 [Null(https://pola-rs.github.io/polars/polars/prelude/struct.Null.html] 表示.

可以通过 null_count, is_null 分别查看列是否包含缺失值, 以及缺失值 bit mask.


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 3, 1, 5, 6],
    "D2" => &[3, 2, 3, 5, 3],
    "D3" => &[Some(9), Some(7), Some(5), Some(2), None]
)?;
println!("{}", df1.null_count());
println!("{}", df1["D3"].is_null().into_series());
}
Output
shape: (1, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ u32 ┆ u32 ┆ u32 │
╞═════╪═════╪═════╡
│ 0   ┆ 0   ┆ 1   │
└─────┴─────┴─────┘
shape: (5,)
Series: 'D3' [bool]
[
        false
        false
        false
        false
        true
]

过滤掉包含缺失值的行


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 2, 3, 4, 5],
    "D2" => &[Some(3), Some(2), None, Some(5), Some(3)],
    "D3" => &[Some(9), Some(7), Some(5), Some(2), None]
)?;
let df2 = df1.lazy().filter(all().is_not_null()).collect()?;
}
Output
shape: (3, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5   ┆ 2   │
└─────┴─────┴─────┘

只针对某个列过滤


#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
    "D1" => &[1, 2, 3, 4, 5],
    "D2" => &[Some(3), Some(2), None, Some(5), Some(3)],
    "D3" => &[Some(9), Some(7), Some(5), Some(2), None]
)?;
let df2 = df1.lazy().filter(col("D3").is_not_null()).collect()?;
println!("{}", df2);
}
Output
shape: (4, 3)
┌─────┬──────┬─────┐
│ D1  ┆ D2   ┆ D3  │
│ --- ┆ ---  ┆ --- │
│ i32 ┆ i32  ┆ i32 │
╞═════╪══════╪═════╡
│ 1   ┆ 3    ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2    ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ null ┆ 5   │
├╌╌╌╌╌┼╌╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5    ┆ 2   │
└─────┴──────┴─────┘

填充缺失值

填充缺失值的方法大概包括

  1. 字面量
  2. 前向或后向填充
  3. 表达式, 例如根据其他列填充
  4. 插值

#![allow(unused)]
fn main() {
let df1: DataFrame = df!(
  "D1" => &[1, 2, 3, 4, 6],
  "D2" => &[3, 2, 8, 5, 3],
  "D3" => &[Some(9), Some(7), None, Some(2), Some(4)]
)?;
// 对全部 null 全部更换为 200
let df2 = df1.clone().lazy().fill_null(lit(200)).collect()?;
println!("对全部 null 全部更换为 200\n{}", df2);

// 以下一个值填充
let df2 = df1
  .clone()
  .lazy()
  .with_column(col("D3").backward_fill(None))
  .collect()?;
println!("以下一个值填充\n{}", df2);

// 以前一个值填充
let df2 = df1
  .clone()
  .lazy()
  .with_column(col("D3").forward_fill(None))
  .collect()?;
println!("以前一个值填充\n{}", df2);

// 插值
let df2 = df1
  .clone()
  .lazy()
  .with_column(col("D3").interpolate())
  .collect()?;
println!("插值\n{}", df2);
}
Output
对全部 null 全部更换为 200
shape: (5, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 8   ┆ 200 │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘
以下一个值填充
shape: (5, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 8   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘
以前一个值填充
shape: (5, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 8   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘
插值
shape: (5, 3)
┌─────┬─────┬─────┐
│ D1  ┆ D2  ┆ D3  │
│ --- ┆ --- ┆ --- │
│ i32 ┆ i32 ┆ i32 │
╞═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 9   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 2   ┆ 2   ┆ 7   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 3   ┆ 8   ┆ 5   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 4   ┆ 5   ┆ 2   │
├╌╌╌╌╌┼╌╌╌╌╌┼╌╌╌╌╌┤
│ 6   ┆ 3   ┆ 4   │
└─────┴─────┴─────┘