{ "cells": [ { "cell_type": "markdown", "id": "520dd0c1-f7f3-43fc-8fde-549a54b637f4", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "
\n", "
\n", "

Beyond pandas:
The great Python dataframe showdown

\n", "

Juan Luis Cano Rodríguez <juanlu@orchest.io>
2022-10-02 @ PyConES 2022 Granada

\n", "
\n", "
" ] }, { "cell_type": "markdown", "id": "a2ef9a3d-170f-4e64-ac97-a1bd3f784352", "metadata": { "slideshow": { "slide_type": "notes" }, "tags": [] }, "source": [ "## Abstract\n", "\n", "The pandas library is one of the key factors that enabled the growth of Python in the Data Science industry and continues to help data scientists thrive almost 15 years after its creation. Because of this success, nowadays there are several open-source projects that claim to improve pandas in various ways, either by bringing it to a distributed computing setting (Dask), accelerating its performance with minimal changes (Modin), or offering slightly different API that solves some of its shortcomings (Polars).\n", "\n", "The outline of the talk goes as follows:\n", "\n", " Short introduction to the importance of pandas, and brief recollection of its main pain points (5 minutes)\n", " Enumeration of some alternatives, description of our classification (pandas-like vs bespoke, single-node vs distributed) (5 minutes)\n", " Presentation of the libraries using brief code snippets, visualization of the dependency relationships between them (20 minutes)\n", " Recommendations and conclusions (5 minutes)\n", "\n", "After the talk, you will have more information on how some of the modern alternatives to pandas fit onto the ecosystem, understand which ones provide the easiest migration path for an existing codebase, and be more prepared to judge which one to use for your next project. Prior exposure to pandas will help make the most of the presentation." ] }, { "cell_type": "markdown", "id": "31ddd403-d8d0-4c61-b361-eefe3c0131af", "metadata": { "slideshow": { "slide_type": "slide" } }, "source": [ "# Outline\n", "\n", "1. Intro\n", "2. pandas: success and limitations\n", "3. The alternatives\n", "4. Demo\n", "5. Conclusions" ] }, { "cell_type": "markdown", "id": "c0e1ab44-de3c-4ce7-8fb2-2296f5c3d33c", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# Who is this guy?\n", "\n", "- Aerospace Engineer on a mission to accelerate the **Solidarity Economy** through technology ♻️\n", "- **Data Scientist Advocate** at Orchest, an open source pipeline orchestrator 🥑\n", "- Organizer of the **PyData Madrid** monthly meetup (ex Python España, ex PyCon Spain) 🐍\n", "- Contributor to the SciPy and PyData ecosystem\n", "- Hard Rock lover 🎸\n", "\n", "Follow me! https://github.com/astrojuanlu/, https://astrojuanlu.substack.com\n", "\n", "![Me!](img/juanlu-orchest.jpg)" ] }, { "cell_type": "markdown", "id": "aa1b554b-14e3-435a-92af-3d5f5dab4951", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "# Data pipelines and dataframes\n", "\n", "- At **Orchest** we want to _empower data scientists_ by developing an easy to use, scalable orchestrator for data pipelines\n", "- Extract + Load is being commoditized, Transform is highly customized and potentially complex\n", "- **\"Am I using the best tools available?\"**\n", "- Focus: dataframe libraries\n", "\n", "![Pipeline](img/pipeline.png)" ] }, { "cell_type": "markdown", "id": "1bc8e25f-a349-47cb-8b90-8f239154ab15", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# pandas: success and limitations\n", "\n", "pandas is everywhere!\n", "\n", "![pandas growth](img/pandas-growth.png)\n", "\n", "https://stackoverflow.blog/2017/09/14/python-growing-quickly/" ] }, { "cell_type": "markdown", "id": "1c7e9956-94dc-4296-95ec-b2d81b9e3d82", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "# pandas: success and limitations\n", "\n", "\"Apache Arrow and the 10 things I hate about pandas\" https://wesmckinney.com/blog/apache-arrow-pandas-internals/\n", "\n", "tl;dr:\n", "\n", "1. Many pandas operations don't take advantage of multiple cores or query planning\n", " - Eager evaluation\n", " - Intermediate objects\n", " - Mixed success with GIL release\n", "2. Lousy memory management\n", " - Handling of missing data is inconsistent\n", " - No memory-mapping\n", " - Strings and categories are inefficient" ] }, { "cell_type": "markdown", "id": "25a2227f-23ab-4559-b683-e270ad263e1b", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# The alternatives" ] }, { "cell_type": "markdown", "id": "7fa89472-d40d-405f-9087-b22b72c2252b", "metadata": { "slideshow": { "slide_type": "fragment" }, "tags": [] }, "source": [ "![pandas alternatives](img/dataframes-charming-quadrangle.png)" ] }, { "cell_type": "markdown", "id": "543ae1b9-1c22-4251-a078-27eee93fe6f4", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "## Apache Arrow\n", "\n", "![Apache Arrow logo](img/apache-arrow.png)\n", "\n", "https://arrow.apache.org/\n", "\n", "\"A language-independent columnar memory format\"\n", "\n", "- Designed for ephemeral, or transient, in-memory storage\n", "- Two formats: **Streaming** and **Random Access**\n", "- To serialize the latter to disk: **Apache Parquet** and **Feather**\n", "- **Immutable**!\n", "- Memory-mapping for fast data processing\n", "- Python bindings (on top of C++), many others\n", "- Not exactly an alternative, but rather a foundation to create them" ] }, { "cell_type": "markdown", "id": "e814b06b-5304-432f-911c-a91a895a4b36", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "## Vaex\n", "\n", "![Vaex logo](img/vaex.png)\n", "\n", "https://vaex.io/\n", "\n", "Out-of-core dataframes \"to visualize and explore big tabular datasets\"\n", "\n", "- Can process **files larger than RAM** thanks to **out-of-core** capabilities\n", "- Initially built around HDF5, now has Parquet support as well\n", "- Rich **visualization** functionality for point clouds (similar to datashader)\n", "- API similar to pandas, with some deviations\n", "- Expression system delays computation (arguably less powerful than Polars')" ] }, { "cell_type": "markdown", "id": "15b2c06d-7e7c-453b-93b3-6d56476bdd06", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "## Polars\n", "\n", "![Polars logo](img/polars.png)\n", "\n", "http://pola.rs/\n", "\n", "\"Lightning-fast\", in-memory dataframes for Rust and Python\n", "\n", "- Uses the Arrow memory format for its columnar storage\n", "- **Eager** and **lazy** modes, even for I/O (\"scanning\")\n", "- **Expressions** ($\\mathcal{F}(\\text{Series}) \\rightarrow \\text{Series}$) are decoupled from the computation itself\n", "- Chains of expressions build an optimized **query plan**\n", "- Powerful row-wise and list-column capabilities\n", "- Young, but very promising" ] }, { "cell_type": "markdown", "id": "252998ca-e02b-4c78-ad37-cbccd1a68945", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "## High performance pandas\n", "\n", "- **cuDF** https://github.com/rapidsai/cudf pandas on GPU\n", "- **Dask** https://dask.org/ distributed pandas (also: Mars, Ray)\n", "- **Modin** https://github.com/modin-project/modin/ transparent pandas acceleration\n", "- **PySpark** https://spark.apache.org/docs/latest/api/python/index.html they've been there this whole time" ] }, { "cell_type": "markdown", "id": "61e7ce27-5c0d-4a40-9513-185c4c61b09c", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# Demo time!\n", "\n", "![Hacker](img/hacker.gif)" ] }, { "cell_type": "markdown", "id": "b294c963-26bf-4761-bc91-88f7b09a5f41", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# What about the index?\n", "\n", "From the Polars docs:\n", "\n", "> Indexes are not needed! Not having them makes things easier - convince us otherwise!\n", "\n", "From Twitter:\n", "\n", "![James Powell on pandas](img/james-powell-pandas.png)\n", "\n", "([Original thread](https://mobile.twitter.com/dontusethiscode/status/1530182008336424963))" ] }, { "cell_type": "markdown", "id": "7171830c-56c5-4eb4-aad0-033be6d689d6", "metadata": { "slideshow": { "slide_type": "subslide" }, "tags": [] }, "source": [ "# Conclusions\n", "\n", "- pandas has some limitations and inconsistencies, and some projects are offering alternatives\n", "- Drop-in replacements are bound to imitate pandas API inconsistencies as well\n", "- Theoretically, certain kinds of operations would be less efficient without an Index - do we care?\n", "- Alternatives look promising, but they are not made for distributed computing (yet?)" ] }, { "cell_type": "markdown", "id": "72454858-ee64-4ff8-b12c-ce78694e2bbc", "metadata": { "slideshow": { "slide_type": "slide" }, "tags": [] }, "source": [ "# Thanks!\n", "\n", "- 📬 juanlu@orchest.io\n", "- 🐦 [@juanluisback](https://twitter.com/juanluisback)\n", "\n", "(Thanks for Kevin Kho, James Powell, Cameron Riddell, Ritchie Vink for inspiration and discussion)\n", "\n", "![pandas alternatives](img/dataframes-charming-quadrangle-scaled.png)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.14" } }, "nbformat": 4, "nbformat_minor": 5 }