On this page:
1.1.3.1 select
1.1.3.2 with-columns
1.1.3.3 filter
1.1.3.4 group-by
1.1.3.5 More complex queries

1.1.3 Expressions and contexts🔗ℹ

Expressions such as (col "weight") describe a computation; a context (select, with-columns, filter, group-by/agg) runs it against a frame.

1.1.3.1 select🔗ℹ
> (~> df
      (select "name"
              (~> (col "birthdate") dt-year (alias "birth_year"))
              (~> (col "weight") (/ (pow (col "height") 2)) (alias "bmi"))))

shape: (4, 3)

┌────────────────┬────────────┬───────────┐

│ name           ┆ birth_year ┆ bmi       │

│ ---            ┆ ---        ┆ ---       │

│ str            ┆ i32        ┆ f64       │

╞════════════════╪════════════╪═══════════╡

│ Alice Archer   ┆ 1997       ┆ 23.791913 │

│ Ben Brown      ┆ 1985       ┆ 23.141498 │

│ Chloe Cooper   ┆ 1983       ┆ 19.687787 │

│ Daniel Donovan ┆ 1981       ┆ 27.134694 │

└────────────────┴────────────┴───────────┘

> (~> df
      (select "name"
              (~> (col "weight") (* 0.95) (round #:decimals 2) (alias "weight-5%"))
              (~> (col "height") (* 0.95) (round #:decimals 2) (alias "height-5%"))))

shape: (4, 3)

┌────────────────┬───────────┬───────────┐

│ name           ┆ weight-5% ┆ height-5% │

│ ---            ┆ ---       ┆ ---       │

│ str            ┆ f64       ┆ f64       │

╞════════════════╪═══════════╪═══════════╡

│ Alice Archer   ┆ 55.0      ┆ 1.48      │

│ Ben Brown      ┆ 68.88     ┆ 1.68      │

│ Chloe Cooper   ┆ 50.92     ┆ 1.57      │

│ Daniel Donovan ┆ 78.94     ┆ 1.66      │

└────────────────┴───────────┴───────────┘

API gaps: no multi-column col("weight", "height"); no name.suffix.

1.1.3.2 with-columns🔗ℹ
> (~> df
      (with-columns (~> (col "birthdate") dt-year (alias "birth_year"))
                    (~> (col "weight") (/ (pow (col "height") 2)) (alias "bmi"))))

shape: (4, 6)

┌────────────────┬────────────┬────────┬────────┬────────────┬───────────┐

│ name           ┆ birthdate  ┆ weight ┆ height ┆ birth_year ┆ bmi       │

│ ---            ┆ ---        ┆ ---    ┆ ---    ┆ ---        ┆ ---       │

│ str            ┆ date       ┆ f64    ┆ f64    ┆ i32        ┆ f64       │

╞════════════════╪════════════╪════════╪════════╪════════════╪═══════════╡

│ Alice Archer   ┆ 1997-01-10 ┆ 57.9   ┆ 1.56   ┆ 1997       ┆ 23.791913 │

│ Ben Brown      ┆ 1985-02-15 ┆ 72.5   ┆ 1.77   ┆ 1985       ┆ 23.141498 │

│ Chloe Cooper   ┆ 1983-03-22 ┆ 53.6   ┆ 1.65   ┆ 1983       ┆ 19.687787 │

│ Daniel Donovan ┆ 1981-04-30 ┆ 83.1   ┆ 1.75   ┆ 1981       ┆ 27.134694 │

└────────────────┴────────────┴────────┴────────┴────────────┴───────────┘

1.1.3.3 filter🔗ℹ
> (~> df (filter (< (dt-year "birthdate") 1990)))

shape: (3, 4)

┌────────────────┬────────────┬────────┬────────┐

│ name           ┆ birthdate  ┆ weight ┆ height │

│ ---            ┆ ---        ┆ ---    ┆ ---    │

│ str            ┆ date       ┆ f64    ┆ f64    │

╞════════════════╪════════════╪════════╪════════╡

│ Ben Brown      ┆ 1985-02-15 ┆ 72.5   ┆ 1.77   │

│ Chloe Cooper   ┆ 1983-03-22 ┆ 53.6   ┆ 1.65   │

│ Daniel Donovan ┆ 1981-04-30 ┆ 83.1   ┆ 1.75   │

└────────────────┴────────────┴────────┴────────┘

> (~> df
      (filter (and (is-between "birthdate"
                               (str->date (lit "1982-12-31"))
                               (str->date (lit "1996-01-01")))
                   (> (col "height") 1.7))))

shape: (1, 4)

┌───────────┬────────────┬────────┬────────┐

│ name      ┆ birthdate  ┆ weight ┆ height │

│ ---       ┆ ---        ┆ ---    ┆ ---    │

│ str       ┆ date       ┆ f64    ┆ f64    │

╞═══════════╪════════════╪════════╪════════╡

│ Ben Brown ┆ 1985-02-15 ┆ 72.5   ┆ 1.77   │

└───────────┴────────────┴────────┴────────┘

API gaps: no date literals, so the bounds parse a string with str->date; filter takes one predicate, so combine with and.

1.1.3.4 group-by🔗ℹ

/ on an integer column is integer division, so Python’s // 10 * 10 is (* (/ e 10) 10).

> (define decade
    (~> (col "birthdate") dt-year (/ 10) (* 10) (alias "decade")))
> (~> df (group-by decade) (agg (~> (col "name") count (alias "len"))))

shape: (2, 2)

┌────────┬─────┐

│ decade ┆ len │

│ ---    ┆ --- │

│ i32    ┆ u32 │

╞════════╪═════╡

│ 1980   ┆ 3   │

│ 1990   ┆ 1   │

└────────┴─────┘

> (~> df
      (group-by decade)
      (agg (~> (col "name") count (alias "sample_size"))
           (~> (col "weight") mean (round #:decimals 2) (alias "avg_weight"))
           (~> (col "height") max (alias "tallest"))))

shape: (2, 4)

┌────────┬─────────────┬────────────┬─────────┐

│ decade ┆ sample_size ┆ avg_weight ┆ tallest │

│ ---    ┆ ---         ┆ ---        ┆ ---     │

│ i32    ┆ u32         ┆ f64        ┆ f64     │

╞════════╪═════════════╪════════════╪═════════╡

│ 1980   ┆ 3           ┆ 69.73      ┆ 1.77    │

│ 1990   ┆ 1           ┆ 57.9       ┆ 1.56    │

└────────┴─────────────┴────────────┴─────────┘

API gaps: no maintain_order, so row order differs from the Python pair; no pl.len() (count a column instead).

1.1.3.5 More complex queries🔗ℹ
> (~> df
      (with-columns decade
                    (str-extract "name" "^(\\S+)"))
      (select (exclude (all) "birthdate"))
      (group-by "decade")
      (agg (col "name")
           (~> (col "weight") mean (round #:decimals 2) (alias "avg_weight"))
           (~> (col "height") mean (round #:decimals 2) (alias "avg_height"))))

shape: (2, 4)

┌────────┬────────────────────────────┬────────────┬────────────┐

│ decade ┆ name                       ┆ avg_weight ┆ avg_height │

│ ---    ┆ ---                        ┆ ---        ┆ ---        │

│ i32    ┆ list[str]                  ┆ f64        ┆ f64        │

╞════════╪════════════════════════════╪════════════╪════════════╡

│ 1980   ┆ ["Ben", "Chloe", "Daniel"] ┆ 69.73      ┆ 1.72       │

│ 1990   ┆ ["Alice"]                  ┆ 57.9       ┆ 1.56       │

└────────┴────────────────────────────┴────────────┴────────────┘

API gaps: no str.split / list.first (regex str-extract instead); no name.prefix.