Table of contents
This is a short comparison of idiomatic pandas, polars and ibis,
all using method chaining.
import sys
sys.version_infosys.version_info(major=3, minor=12, micro=5, releaselevel='final', serial=0)import ibisfrom ibis import _ibis.options.interactive = Trueibis.__version__'9.4.0'df = ibis.examples.starwars.fetch()df┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ height ┃ mass ┃ hair_color ┃ skin_color ┃ eye_color ┃ birth_year ┃ sex ┃ gender ┃ homeworld ┃ species ┃ films ┃ vehicles ┃ starships ┃ ┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩ │ string │ int64 │ float64 │ string │ string │ string │ float64 │ string │ string │ string │ string │ string │ string │ string │ ├────────────────────┼────────┼─────────┼───────────────┼─────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤ │ Luke Skywalker │ 172 │ 77.0 │ blond │ fair │ blue │ 19.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ C-3PO │ 167 │ 75.0 │ NULL │ gold │ yellow │ 112.0 │ none │ masculine │ Tatooine │ Droid │ NULL │ NULL │ NULL │ │ R2-D2 │ 96 │ 32.0 │ NULL │ white, blue │ red │ 33.0 │ none │ masculine │ Naboo │ Droid │ NULL │ NULL │ NULL │ │ Darth Vader │ 202 │ 136.0 │ none │ white │ yellow │ 41.9 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Leia Organa │ 150 │ 49.0 │ brown │ light │ brown │ 19.0 │ female │ feminine │ Alderaan │ Human │ NULL │ NULL │ NULL │ │ Owen Lars │ 178 │ 120.0 │ brown, grey │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Beru Whitesun Lars │ 165 │ 75.0 │ brown │ light │ blue │ 47.0 │ female │ feminine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ R5-D4 │ 97 │ 32.0 │ NULL │ white, red │ red │ NULL │ none │ masculine │ Tatooine │ Droid │ NULL │ NULL │ NULL │ │ Biggs Darklighter │ 183 │ 84.0 │ black │ light │ brown │ 24.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Obi-Wan Kenobi │ 182 │ 77.0 │ auburn, white │ fair │ blue-gray │ 57.0 │ male │ masculine │ Stewjon │ Human │ NULL │ NULL │ NULL │ │ … │ … │ … │ … │ … │ … │ … │ … │ … │ … │ … │ … │ … │ … │ └────────────────────┴────────┴─────────┴───────────────┴─────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘
Pandas
import re
M = 100
_df = ( df .to_pandas() .rename(lambda col: re.sub(r'(?<!^)(?=[A-Z])', '_', col).lower(), axis=1) .query("height > 100") .query("mass > @M") .query('hair_color.str.contains("brown") == True') # some values can be `None` so explicit True required .query("sex.notna()") .assign(hair_color = lambda c: c.hair_color.str.split(',')) .explode("hair_color") .query("birth_year.notna()"))
ibis.pandas.connect({'_df': _df}).table('_df')┏━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ height ┃ mass ┃ hair_color ┃ skin_color ┃ eye_color ┃ birth_year ┃ sex ┃ gender ┃ homeworld ┃ species ┃ films ┃ vehicles ┃ starships ┃ ┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩ │ string │ float64 │ float64 │ string │ string │ string │ float64 │ string │ string │ string │ string │ null │ null │ null │ ├───────────┼─────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼───────┼──────────┼───────────┤ │ Owen Lars │ 178.0 │ 120.0 │ brown │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Owen Lars │ 178.0 │ 120.0 │ grey │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Chewbacca │ 228.0 │ 112.0 │ brown │ unknown │ blue │ 200.0 │ male │ masculine │ Kashyyyk │ Wookiee │ NULL │ NULL │ NULL │ └───────────┴─────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴───────┴──────────┴───────────┘
Polars
import reimport polars as pl
M = 100
_df = ( df .to_polars() .rename(lambda col: re.sub(r'(?<!^)(?=[A-Z])', '_', col).lower()) .filter(pl.col("height") > 100) .filter(pl.col("mass") > M) .filter(pl.col("hair_color").str.contains("brown")) .filter(pl.col("sex").is_not_null()) .with_columns(pl.col("hair_color").str.split(",").alias("hair_color")) .explode(pl.col("hair_color")) .filter(pl.col("birth_year").is_not_null()))
ibis.polars.connect({'_df': _df}).table('_df')┏━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ height ┃ mass ┃ hair_color ┃ skin_color ┃ eye_color ┃ birth_year ┃ sex ┃ gender ┃ homeworld ┃ species ┃ films ┃ vehicles ┃ starships ┃ ┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩ │ string │ int64 │ float64 │ string │ string │ string │ float64 │ string │ string │ string │ string │ string │ string │ string │ ├───────────┼────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤ │ Owen Lars │ 178 │ 120.0 │ brown │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Owen Lars │ 178 │ 120.0 │ grey │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Chewbacca │ 228 │ 112.0 │ brown │ unknown │ blue │ 200.0 │ male │ masculine │ Kashyyyk │ Wookiee │ NULL │ NULL │ NULL │ └───────────┴────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘
ibis
M = 100_df = ( df .rename("snake_case") .filter(_.height > 100) .filter(_.mass > M) .filter(_.hair_color.contains("brown")) .filter(_.sex.notnull()) .mutate(hair_color = _.hair_color.split(",")) .unnest(_.hair_color) .drop_null(_.birth_year))
_df┏━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━┓ ┃ name ┃ height ┃ mass ┃ hair_color ┃ skin_color ┃ eye_color ┃ birth_year ┃ sex ┃ gender ┃ homeworld ┃ species ┃ films ┃ vehicles ┃ starships ┃ ┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩ │ string │ int64 │ float64 │ string │ string │ string │ float64 │ string │ string │ string │ string │ string │ string │ string │ ├───────────┼────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤ │ Owen Lars │ 178 │ 120.0 │ brown │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Owen Lars │ 178 │ 120.0 │ grey │ light │ blue │ 52.0 │ male │ masculine │ Tatooine │ Human │ NULL │ NULL │ NULL │ │ Chewbacca │ 228 │ 112.0 │ brown │ unknown │ blue │ 200.0 │ male │ masculine │ Kashyyyk │ Wookiee │ NULL │ NULL │ NULL │ └───────────┴────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘