Skip to content
kd
25 Aug 2024
Back to blog

Pandas vs Polars vs ibis

3 min read (472 words)

Table of contents

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      │
└───────────┴────────┴─────────┴────────────┴────────────┴───────────┴────────────┴────────┴───────────┴───────────┴─────────┴────────┴──────────┴───────────┘

Citation

@online{krishnamurthy2024pandasvspolarsvsibis,
  author = {Dheepak Krishnamurthy},
  title = {Pandas vs Polars vs ibis},
  year = {2024},
  date = {2024-08-25},
  url = {https://kdheepak.com/blog/pandas-vs-polars-vs-ibis/},
  langid = {en},
}

For attribution, please cite this work as:

Dheepak Krishnamurthy, "Pandas vs Polars vs ibis", August 25, 2024 https://kdheepak.com/blog/pandas-vs-polars-vs-ibis/


Power Lines with `ibis`
The Basic Building blocks of Ratatui - Part 5