Custom pivot_ui aggregator in python?

590 Views Asked by At

Is there a way to create a custom aggregator for pivot_ui in python? I'd like to do weighted averages and hide the details of the computation/field-mappings from users, and only provide meaningful labels in the custom aggregator dropdown. All examples of custom aggregators are in javascript. Is there a way to do it in python/jupyter?

eg. in javascript: ( from view-source:http://horner.github.io/pivottable/examples/montreal_2014.html )

    $(function () {
        var tpl =              $.pivotUtilities.aggregatorTemplates;
        $.get("montreal_2014.csv", function(montreal_2014) {
            $("#output").pivotUI($.csv.toArrays(montreal_2014), {
                aggregators: {
                    "Mean Temp (Celcius)":  
                        function() { return tpl.average()(["Mean Temp (C)"])},

in python:

from pivottablejs import pivot_ui
pivot_ui( df, rows=["day"], aggregators= ?? )

How do I define and pass a javascript function obj in jupyter notebook? could I somehow define it with %%javascript in a different cell and reference in python? or is there some magic in the streamlit.components.v1 that can accomplish this?

thanks

2

There are 2 best solutions below

0
Ailurophile On

Looking at the pivottablejs library for Python, it looks like they return an IFrame. You can try components.html form Streamlit

import streamlit as st
import streamlit.components.v1 as components
from pivottablejs import pivot_ui
import pandas as pd


t = pivot_ui(df)

with open(t.src) as t:
    components.html(t.read(), width=900, height=1000, scrolling=True)
0
Anatoly Bugakov On

Consider using ultibi instead. It was build especially for custom aggregators, which you can define in python or rust. The repo has good examples, here is a quick one:

import ultibi as ul
import polars as pl
import os
os.environ["RUST_LOG"] = "info" # enable logs
os.environ["ADDRESS"] = "0.0.0.0:8000" # host on this address

# Read Data
# for more details: https://pola-rs.github.io/polars/py-polars/html/reference/api/polars.read_csv.html
df = pl.read_csv("titanic.csv")

# Let's add some Custom Aggregators to our UI

# Standard Calculator - does not block GIL
def survival_mean_age(kwargs: dict[str, str]) -> pl.Expr:
    """Mean Age of Survivals
    pl.col("survived") is 0 or 1
    pl.col("age") * pl.col("survived") - age of survived person, otherwise 0
    pl.col("survived").sum() - number of survived
    """
    return pl.col("age") * pl.col("survived") / pl.col("survived").sum()

measures = [ ul.BaseMeasure(
                "SurvivalMeanAge",
                ul.StandardCalculator(survival_mean_age),
                aggregation_restriction="sum",
            ) ]
#create ul.DataSet
ds = ul.DataSet.from_frame(df, bespoke_measures=measures)
# host ui
ds.ui() 

You can find out the full power of custom aggregators (beyond polars expressions) in the relevant section of the userguide.