Pandas vs Polars vs ibis

Author

Dheepak Krishnamurthy

Published

August 25, 2024

This is a short comparison of idiomatic pandas, polars and ibis, all using method chaining.

import sys

sys.version_info
sys.version_info(major=3, minor=12, micro=5, releaselevel='final', serial=0)
import ibis
from ibis import _
ibis.options.interactive = True
ibis.__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 ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩
│ stringint64float64stringstringstringfloat64stringstringstringstringstringstringstring    │
├────────────────────┼────────┼─────────┼───────────────┼─────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤
│ Luke Skywalker    17277.0blond        fair       blue     19.0male  masculineTatooine Human  NULLNULLNULL      │
│ C-3PO             16775.0NULLgold       yellow   112.0none  masculineTatooine Droid  NULLNULLNULL      │
│ R2-D2             9632.0NULLwhite, bluered      33.0none  masculineNaboo    Droid  NULLNULLNULL      │
│ Darth Vader       202136.0none         white      yellow   41.9male  masculineTatooine Human  NULLNULLNULL      │
│ Leia Organa       15049.0brown        light      brown    19.0femalefeminine Alderaan Human  NULLNULLNULL      │
│ Owen Lars         178120.0brown, grey  light      blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Beru Whitesun Lars16575.0brown        light      blue     47.0femalefeminine Tatooine Human  NULLNULLNULL      │
│ R5-D4             9732.0NULLwhite, red red      NULLnone  masculineTatooine Droid  NULLNULLNULL      │
│ Biggs Darklighter 18384.0black        light      brown    24.0male  masculineTatooine Human  NULLNULLNULL      │
│ Obi-Wan Kenobi    18277.0auburn, whitefair       blue-gray57.0male  masculineStewjon  Human  NULLNULLNULL      │
│          │
└────────────────────┴────────┴─────────┴───────────────┴─────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘

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 ┃
┡━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩
│ stringfloat64float64stringstringstringfloat64stringstringstringstringnullnullnull      │
├───────────┼─────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼───────┼──────────┼───────────┤
│ Owen Lars178.0120.0brown     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Owen Lars178.0120.0 grey     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Chewbacca228.0112.0brown     unknown   blue     200.0male  masculineKashyyyk WookieeNULLNULLNULL      │
└───────────┴─────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴───────┴──────────┴───────────┘

Polars

import re
import 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 ┃
┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩
│ stringint64float64stringstringstringfloat64stringstringstringstringstringstringstring    │
├───────────┼────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤
│ Owen Lars178120.0brown     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Owen Lars178120.0 grey     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Chewbacca228112.0brown     unknown   blue     200.0male  masculineKashyyyk WookieeNULLNULLNULL      │
└───────────┴────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘

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 ┃
┡━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━┩
│ stringint64float64stringstringstringfloat64stringstringstringstringstringstringstring    │
├───────────┼────────┼─────────┼────────────┼────────────┼───────────┼────────────┼────────┼───────────┼───────────┼─────────┼────────┼──────────┼───────────┤
│ Owen Lars178120.0brown     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Owen Lars178120.0 grey     light     blue     52.0male  masculineTatooine Human  NULLNULLNULL      │
│ Chewbacca228112.0brown     unknown   blue     200.0male  masculineKashyyyk WookieeNULLNULLNULL      │
└───────────┴────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘

Reuse

Citation

BibTeX citation:
@online{krishnamurthy2024,
  author = {Krishnamurthy, Dheepak},
  title = {Pandas Vs {Polars} Vs Ibis},
  date = {2024-08-25},
  url = {https://kdheepak.com/blog/pandas-vs-polars-vs-ibis/},
  langid = {en}
}
For attribution, please cite this work as:
D. Krishnamurthy, “Pandas vs Polars vs ibis,” Aug. 25, 2024. https://kdheepak.com/blog/pandas-vs-polars-vs-ibis/.