Skip to main content
marimo provides powerful interactive dataframe components that let you explore, filter, sort, and transform your data directly in the UI.

Supported Libraries

marimo supports multiple dataframe libraries:
  • pandas - The most popular Python data analysis library
  • polars - High-performance DataFrame library
  • pyarrow - Apache Arrow in Python
  • ibis - Unified interface for SQL and dataframes
  • DuckDB - In-process SQL database
All dataframe operations use narwhals under the hood for efficient, library-agnostic transformations.

Basic Usage

import marimo as mo
import pandas as pd

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Charlie"],
    "age": [25, 30, 35],
    "city": ["NYC", "SF", "LA"]
})

mo.ui.dataframe(df)

Interactive Transformations

The mo.ui.dataframe component allows users to apply transformations through the UI:
1
Filter Rows
2
Click the filter icon to add conditions:
3
  • Comparison operators: ==, !=, <, >, <=, >=
  • String operations: contains, starts_with, ends_with, regex
  • Null checks: is_null, is_not_null
  • Set operations: in, not_in
  • 4
    Sort Columns
    5
    Click column headers to sort ascending or descending, with control over NA position.
    6
    Select Columns
    7
    Choose which columns to display using the column selector.
    8
    Aggregate Data
    9
    Group by columns and apply aggregations:
    10
  • count, sum, mean, median, min, max
  • 11
    Advanced Operations
    12
  • Rename columns - Change column names
  • Convert types - Change data types with error handling
  • Sample rows - Random sampling with or without replacement
  • Shuffle rows - Randomize row order
  • Remove duplicates - Keep first, last, or no duplicates
  • Accessing Transformed Data

    import marimo as mo
    import pandas as pd
    
    df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
    df_widget = mo.ui.dataframe(df)
    
    In another cell:
    # Access the transformed dataframe
    transformed_df = df_widget.value
    
    # The transformed data is in the same format as the input
    type(transformed_df)  # pandas.DataFrame
    

    Configuration Options

    mo.ui.dataframe(
        df,
        page_size=10,              # Rows per page
        show_download=True,        # Show download button
        lazy=False,                # Apply transforms immediately
        limit=10000,               # Load limit for remote data
        format_mapping={           # Format specific columns
            "price": "${:.2f}".format,
            "percentage": lambda x: f"{x*100:.1f}%"
        }
    )
    

    Format Mapping

    Customize how values are displayed:
    import marimo as mo
    import pandas as pd
    
    def format_name(name):
        return name.upper()
    
    df = pd.DataFrame({
        "name": ["alice", "bob"],
        "score": [95.5, 87.3]
    })
    
    mo.ui.dataframe(
        df,
        format_mapping={
            "name": format_name,
            "score": "{:.1f}".format
        }
    )
    

    Lazy Evaluation

    For large datasets or lazy dataframes (Polars LazyFrame, Ibis), marimo automatically enables lazy mode:
    import polars as pl
    import marimo as mo
    
    # LazyFrame - transformations build a query plan
    lazy_df = pl.scan_csv("large_file.csv")
    
    # Lazy mode enabled automatically
    mo.ui.dataframe(lazy_df)
    
    With lazy mode, an “Apply” button appears - transformations are only executed when clicked.

    Export Options

    Users can download transformed data in multiple formats:
    • CSV - With configurable encoding and separator
    • JSON - With ASCII encoding option
    • Parquet - Efficient columnar format
    mo.ui.dataframe(
        df,
        download_csv_encoding="utf-8-sig",  # Include BOM for Excel
        download_csv_separator=";",          # Use semicolon
        download_json_ensure_ascii=True      # Escape non-ASCII
    )
    

    Code Generation

    marimo can generate Python code for the transformations applied in the UI:
    df_widget = mo.ui.dataframe(df)
    
    # After applying transformations in the UI
    transformed = df_widget.value
    
    # Get the equivalent Python code
    # This is available internally and shown in the UI
    
    Transformations are reactive - when you apply filters or sorts in the UI, df_widget.value automatically updates in dependent cells.

    Selection and Tables

    For row/cell selection without transformations, use mo.ui.table instead:
    table = mo.ui.table(
        df,
        selection="multi",  # or "single", "single-cell", "multi-cell"
        pagination=True
    )
    
    # Access selected rows
    selected = table.value
    
    See the Tables guide for more details.

    Performance Tips

    For DataFrames with more than 100,000 rows, lazy mode is automatically enabled to prevent loading all data into memory.
    • Use limit parameter for remote/lazy data sources
    • Enable lazy=True for expensive transformations
    • Consider Polars LazyFrame for very large datasets
    • Use page_size to control initial rendering cost

    Example: Complete Workflow

    import marimo as mo
    import pandas as pd
    
    # Create sample data
    df = pd.DataFrame({
        "product": ["A", "B", "C", "A", "B"],
        "sales": [100, 150, 200, 120, 180],
        "region": ["North", "South", "North", "South", "North"],
        "date": pd.date_range("2024-01-01", periods=5)
    })
    
    # Create interactive dataframe
    df_widget = mo.ui.dataframe(
        df,
        page_size=5,
        format_mapping={
            "sales": "${:,.0f}".format
        }
    )
    
    In another cell:
    # Use transformed data for analysis
    filtered_df = df_widget.value
    
    # The dataframe reflects all UI transformations
    mo.md(f"""
    ## Analysis Results
    
    Total Sales: ${filtered_df['sales'].sum():,.0f}
    
    Average: ${filtered_df['sales'].mean():,.2f}
    """)
    

    Build docs developers (and LLMs) love