vega / altair

Declarative statistical visualization library for Python
https://altair-viz.github.io/
BSD 3-Clause "New" or "Revised" License
9.24k stars 787 forks source link

Python expressions cannot be used where the entire expression is an array #3605

Open joelostblom opened 11 hours ago

joelostblom commented 11 hours ago

What is your suggestion?

In the code below, we combine columns into an array by passing them as a list inside the JS expression string. This is not possible to replicate with a python expression using alt.datum since transform calculate will not accept a list (and neither will alt.expr). This is another case (in addition to https://github.com/vega/altair/issues/3366 where the python expression don't cover everything the JS expressions can do), and it would be great if we could somehow support using python expressions for this too (maybe we need alt.expr.array(...) or similar?).

import pandas as pd
import altair as alt

mpg = pd.read_csv('https://raw.githubusercontent.com/has2k1/plotnine/4159f9548fa5f95c02366efc324e88f9ba79af09/plotnine/data/mpg.csv')

alt.Chart(mpg, width=100, height=100).mark_point().transform_calculate(
    man_model_drv='[datum.manufacturer, datum.model, datum.drv]'
    # Does not work
    # man_model_drv=[alt.datum.manufacturer, alt.datum.model, alt.datum.drv]
).encode(
    x='cty',
    y='hwy',
).facet(
    'man_model_drv:N',
    columns=7
)

ref https://github.com/vega/altair/discussions/3601#discussioncomment-10698263

Have you considered any alternative solutions?

No response

dangotbanned commented 6 hours ago

merge seems to be the closest in terms of signature, but this accepts object - not sure if that works?

Otherwise I think we'd need vega to implement a toArray type coercion function like:

toArray(value1[, value2, ...])

joelostblom commented 3 hours ago

Good idea to try merge, but unfortunately it doesn't work:

image

It did, however, give me the idea to try out slice and that does in fact work.

man_model_drv=alt.expr.slice([alt.datum.manufacturer, alt.datum.model, alt.datum.drv])

While it is not the most intuitive, it is at least convenient to type out. Not sure if it is still worthwhile creating toArray in VL, or just using slice when it is needed. Another option would be to just create expr.array(...) in altair as an alias for expr.slice(..., 0).

dangotbanned commented 2 hours ago

Good idea to try merge, but unfortunately it doesn't work:

image

It did, however, give me the idea to try out slice and that does in fact work.

man_model_drv=alt.expr.slice([alt.datum.manufacturer, alt.datum.model, alt.datum.drv])

Interesting 🤔

I've been reading the docs for these a lot in #3600 and that was not what I expected would happen - but great that it works