Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Lifting parameters to the top level #2684

Closed
wants to merge 14 commits into from
Closed

WIP: Lifting parameters to the top level #2684

wants to merge 14 commits into from

Conversation

ChristopherDavisUCI
Copy link
Contributor

Updated version of #2671. I believe the functionality is the same, but the code is a little cleaner. @mattijn As always I am happy for any comments!

Here was the description of #2671:

This is a draft version (some tests are currently failing) of the strategy suggested by @arvind and @mattijn here for dealing with parameters in multi-view Altair charts. We lift all parameters to the top level. In the case of selection parameters, we give the parameter a "views" property to indicate where the selections should be happening.

@ChristopherDavisUCI
Copy link
Contributor Author

@mattijn I haven't worked on the Vega-Lite issues you raised in #2671 (comment). If this code seems to be working for you (and not too complicated), I will start thinking about those issues.

Also if we decide this is working as expected, I will go through the 8 (?) failing tests and either change the tests or update my code.

@mattijn
Copy link
Contributor

mattijn commented Sep 26, 2022

Great @ChristopherDavisUCI! Looks more readable. I like the changes.

You might align these definitions:
https://github.com/ChristopherDavisUCI/altair/blob/liftparams/tools/generate_schema_wrapper.py#L29-L30

with the changes you introduced here: https://github.com/altair-viz/altair/blob/70682835bd4d80e31a378890f6f2274501cf2849/altair/vega/v5/schema/__init__.py

including a run of the generate_schema_wrapper.py, since:

!python -m pip install git+https://github.com/ChristopherDavisUCI/altair.git@liftparams
import altair as alt
alt.SCHEMA_VERSION

gives me v5.2.0.

I checked a few of these failing tests and they seem to be related to the more recent discussion we had regarding the behaviour of layered params. These tests seems compact and interesting and I did not really see a case that require changing the tests assertion of these failing tests (excluding interactive_layered_crossfilter.py).

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks @mattijn! I see now that I had updated the Vega version in the wrong place; it should be corrected now. I also updated vega-lite to 5.5.0. Does that sound like what you had in mind? (It looks like the Vega-Lite editor uses vega-lite 5.2.0.)

I'll take a closer look at the failing tests soon.

@ChristopherDavisUCI
Copy link
Contributor Author

@mattijn Here's one concern I have related to the failing tests. If I understand right, the failing layer chart test, for example, asserts that adding a selection parameter to a LayerChart should be the same as adding a selection parameter to the first chart in the layer list. I think that should be easy to implement, but what if a later version of Vega-Lite says these two parameter placements should both be allowed and should behave differently? Do you see what I'm worried about?

If you think that sort of hypothetical future issue could be fixed easily enough later, I'll go ahead and try to add functionality so there is more flexibility in placing selection parameters on top level charts.

@mattijn
Copy link
Contributor

mattijn commented Sep 27, 2022

I think I understand what you mean. I think I've raised and discuss this in this VL-issue, vega/vega-lite#7854 (comment).

At the moment we can assume that multiple selection parameter placements within a layered chart results in potentially interference and that therefor a single layered object can only have 1 name/view combination.

I see it as a single name definition on the full layer-object, like the following in VL-json:

"layer": [
    "name":"view_0", 
    {}, 
    {}
]

But this type of structure is not allowed within VL.

We might still opt for defining this as such and then change it (including a comment) subsequently into:

"layer": [   
    {"name":"view_0"}, 
    {}
]

Then when this behavior is potentially changing in the future, it is potentially easier to adapt to these changes.

This approach might also help in presenting a user-friendly error when defining two different selection parameters in the layer or for resolving two equal defined selection parameters in the layer (see also #2671 (comment)).

@ChristopherDavisUCI
Copy link
Contributor Author

ChristopherDavisUCI commented Sep 29, 2022

Edit As I think about it, maybe the parameter should only be distributed if it doesn't have a views property already? Overall these fixes feel a little ad hoc to me...

Hi @mattijn, I fixed three of the failing tests (for concat, hconcat, vconcat) by doing the following:

Does that all sound reasonable? An alternative option to resetting the _counter would be to weaken the requirements that the dictionaries be identical.

@mattijn
Copy link
Contributor

mattijn commented Sep 30, 2022

I don't see a problem for resetting the _counter instance when comparing two Chart objects created after each other.

Edit As I think about it, maybe the parameter should only be distributed if it doesn't have a views property already? Overall these fixes feel a little ad hoc to me...

Hm, not sure..
Given:

base = alt.Chart("data.csv").mark_point()
selection = alt.selection_point()

Then for concatenating, this is proper VL-style:

chart1 = alt.concat(base.add_params(selection), base.add_params(selection))

This is not proper VL-style, but allowed by Altair:

chart2 = alt.concat(base, base).add_params(selection)

So, doing a redistribution there for the h/v/concat seems valid to me.

Thinking a bit more, I do agree that one cannot just blindly distribute all params to all objects within concat:
Eg. this will not work:

alt.concat(alt.layer(base, base), alt.layer(base, base)).add_params(selection)

But then it should be somehow recognize to do:

alt.concat(alt.layer(base.add_params(selection), base), alt.layer(base.add_params(selection), base))

Edit: the tests I considered:

!python -m pip install git+https://github.com/ChristopherDavisUCI/altair.git@liftparams
import altair as alt
from vega_datasets import data

def test_compound_add_selections(charttype):
    base = alt.Chart("data.csv").mark_point()
    selection = alt.selection_point()
    alt.Chart._counter = 0
    chart1 = charttype(base.add_params(selection), base.add_params(selection))
    alt.Chart._counter = 0
    chart2 = charttype(base, base).add_params(selection)
    print(f'{chart1.to_dict()}\n{chart2.to_dict()}')
    #assert chart1.to_dict() == chart2.to_dict()

def test_repeat_add_selections():
    base = alt.Chart("data.csv").mark_point()
    selection = alt.selection_point()
    chart1 = base.add_params(selection).repeat(list("ABC"))
    chart2 = base.repeat(list("ABC")).add_params(selection)
    print(f'{chart1.to_dict()}\n{chart2.to_dict()}')
    #assert chart1.to_dict() == chart2.to_dict()

def test_facet_add_selections():
    base = alt.Chart("data.csv").mark_point()
    selection = alt.selection_point()
    chart1 = base.add_params(selection).facet("val:Q")
    chart2 = base.facet("val:Q").add_params(selection)
    print(f'{chart1.to_dict()}\n{chart2.to_dict()}')    
    #assert chart1.to_dict() == chart2.to_dict()

def test_layer_add_selection():
    base = alt.Chart("data.csv").mark_point()
    selection = alt.selection_point()
    chart1 = alt.layer(base.add_params(selection), base)
    chart2 = alt.layer(base, base).add_params(selection)
    print(f'{chart1.to_dict()}\n{chart2.to_dict()}')
    #assert chart1.to_dict() == chart2.to_dict()    

def test_interactive_layered_crossfilter():
    source = alt.UrlData(
        data.flights_2k.url,
        format={'parse': {'date': 'date'}}
    )

    brush = alt.selection(type='interval', encodings=['x'])

    # Define the base chart, with the common parts of the
    # background and highlights
    base = alt.Chart(source).mark_bar().encode(
        x=alt.X(alt.repeat('column'), type='quantitative', bin=alt.Bin(maxbins=20)),
        #x=alt.X('distance', type='quantitative', bin=alt.Bin(maxbins=20)),    
        y='count()'
    ).properties(
        width=160,
        height=130
    )

    # gray background with selection
    background = base.encode(
        color=alt.value('#ddd')
    ).add_params(brush)

    # blue highlights on the transformed data
    highlight = base.transform_filter(brush)

    # layer the two charts & repeat
    chart = alt.layer(
        background,
        highlight,
        data=source
    ).transform_calculate(
        "time",
        "hours(datum.date)"
    ).repeat(column=["distance", "delay", "time"])
    #assert chart
    print(f'{chart.to_dict()}')

for charttype in [alt.concat, alt.hconcat, alt.vconcat]:
    print(charttype)
    test_compound_add_selections(charttype)

test_repeat_add_selections()
test_facet_add_selections()
test_layer_add_selection()
test_interactive_layered_crossfilter() 

Reverting back to the old definitions of `add_params`.  Also resetting `_counter` in a test.
@ChristopherDavisUCI
Copy link
Contributor Author

Hi @mattijn, I think the only failing tests at this point are the two related to test_interactive_layered_crossfilter. And as far as I understand, I don't think we know how to generate this chart with our current strategy.

Do you see a "parameters at the top level with named views" version of this Vega-Lite schema that is allowed? https://vega.github.io/vega-lite/examples/interactive_layered_crossfilter.html Or should we just resign ourselves to our strategy not working for this example at the moment?

@mattijn
Copy link
Contributor

mattijn commented Oct 3, 2022

Great progress @ChristopherDavisUCI! Well done.
Regarding the repeat operator, yes, let's not focus too much on this in this PR.

I tried a few things and I think this is working pretty good.

Still a question:
In #2671 (comment) there were 4 scenarios from which only scenario 1 was working. Now scenario 2 also works with the latest changes, but scenario 3 & 4 do still give errors.

Do you think this is something that should be resolved within this PR?

@mattijn
Copy link
Contributor

mattijn commented Oct 4, 2022

I had another go using repeat and params: vega/vega-lite#6890 (comment). It seems there is more possible than first anticipated (I think we want option 3 & 6, but is option 2 also acceptable here?).

@ChristopherDavisUCI
Copy link
Contributor Author

ChristopherDavisUCI commented Oct 5, 2022

Those six examples you provided vega/vega-lite#6890 (comment) are super helpful @mattijn.

I haven't wrapped my head around the different scenarios yet. Just as a big-picture overview, do you think your option 6 will give us a way to produce this example with the params at the top level?
https://vega.github.io/vega-lite/examples/interactive_layered_crossfilter.html

(At least in this PR, I think we should try to consistently have params appear at the top level.)

@mattijn
Copy link
Contributor

mattijn commented Oct 5, 2022

Yes I think so. We should at least be able to get a Vega-Lite spec that compiles. The interaction and axis will not be perfect, since these VL-bug(s): vega/vega-lite#8446, which is hopefully a duplicate of vega/vega-lite#8348, but we should be able to get a chart that renders.

If we instead focus on the Altair version of option 6, we can test better.
Here the Altair spec with repeat commented out:

!python -m pip install git+https://github.com/ChristopherDavisUCI/altair.git@liftparams
import pandas as pd
import altair as alt
source = pd.read_csv('https://unpkg.com/[email protected]/data/weather.csv')

highlight = alt.selection_point(
    nearest=True, on="mouseover", encodings=["x"], clear="mouseout"
)
rule = (
    alt.Chart()
    .mark_rule()
    .encode(
        x=alt.X("month(date):T"),
        color=alt.value("black"),
        opacity=alt.condition(highlight, alt.value(1), alt.value(0), empty=False),
    )
)

line = (
    alt.Chart()
    .mark_line(point=True)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),  
        #y=alt.Y(alt.repeat('repeat'), aggregate='mean'),
        color=alt.Color("location:N"),
    )
)

alt.layer(rule, line, data=source, height=200, width=200).add_params(
    highlight
)#.repeat(repeat=["temp_max", "precipitation", "wind"])

If I add the repeat operator and change the y encoding to use the repeat, I get the following error:

SchemaValidationError: Invalid specification

        altair.vegalite.v5.schema.channels.OpacityValue, validating 'additionalProperties'

        Additional properties are not allowed ('param', 'empty' were unexpected)
        
alt.RepeatChart(...)

This should compile, so we still miss something in the alt.RepeatChart()?

@ChristopherDavisUCI
Copy link
Contributor Author

Hi @mattijn, thanks for the continued testing! I think I got the RepeatChart issue fixed. I haven't thought yet about your scenarios 3 and 4 that you mentioned in #2671 (comment) (but can confirm they're still not working). I will think about that now.

Could you please take another look and see if things are now behaving mostly as you expected?

Is it obvious to you which tests have failed in the Python 3.9 build? On my end they seem to be passing.

@mattijn
Copy link
Contributor

mattijn commented Oct 8, 2022

Tests on Github Actions are failing because this PR in the altair_viewer repository is not yet merged: altair-viz/altair_viewer#51.
I test your latests changes and all seems fine to me. Nice!
I noticed there is still one assert in your latest commits, you probably didn't want to include this: b79460d#diff-bbe4e187b18d242a366c820d023afd89041759cb96e4ec66c3f34559a72c2f9dR2332

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks as always for the feedback @mattijn. I think your four scenarios from #2671 (comment) are currently working.
Could you please check and see if you agree? Anything overall that seems not to be working?

@mattijn
Copy link
Contributor

mattijn commented Oct 9, 2022

Nice as always @ChristopherDavisUCI!
For the following layered facet chart, I still have two different errors. The first specification is a layered facet chart without parameters defined:

import altair as alt
from vega_datasets import data

iris = data.iris.url
hover = alt.selection_point(on='mouseover', nearest=True)

base = alt.Chart().encode(
    x='petalLength:Q',
    y='petalWidth:Q',
    color='species:N'  # alt.condition(hover, 'species:N', alt.value('lightgray'))
).properties(
    width=180,
    height=180,
).add_params(hover)

points = base.mark_point()

text = base.mark_text(dy=-5).encode(
    text = 'species:N',
    opacity = alt.value(1)  # alt.condition(hover, alt.value(1), alt.value(0), empty=False)
)

chart = alt.layer(points, text, data=iris).facet(
    'species:N',
)  # .add_params(hover)

chart  # .to_dict()

Returns:

SchemaValidationError: Invalid specification
        altair.vegalite.v5.api.Chart, validating 'required'
        'data' is a required property        
alt.FacetChart(...)

Not sure where I should add my data, I tried within Chart(), within layer(data=iris) and facet(data=iris), but always the same error.

And the second layered facet chart including defined parameters:

import altair as alt
from vega_datasets import data

iris = data.iris.url
hover = alt.selection_point(on='mouseover', nearest=True)

base = alt.Chart().encode(
    x='petalLength:Q',
    y='petalWidth:Q',
    color=alt.condition(hover, 'species:N', alt.value('lightgray'))  # 'species:N'
).properties(
    width=180,
    height=180,
).add_params(hover)

points = base.mark_point()

text = base.mark_text(dy=-5).encode(
    text='species:N',
    opacity=alt.condition(hover, alt.value(1), alt.value(0), empty=False)  # alt.value(1)
)

chart = alt.layer(points, text).facet(
    'species:N',
    data=iris
).add_params(hover)

chart  # .to_dict()`

Gives me:

SchemaValidationError: Invalid specification
        altair.vegalite.v5.schema.channels.Color, validating 'additionalProperties'
        Additional properties are not allowed ('param' was unexpected)        
alt.FacetChart(...)

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks @mattijn! These "data missing" error messages usually mean the parameters are in the wrong place, and that seems to be the case here. I'll take a look.

@ChristopherDavisUCI
Copy link
Contributor Author

Hi @mattijn, luckily it seems like the same fix that worked for LayerChart also works in this case. Do your examples now seem to be working? Please keep sending any non-working examples you can come up with!

@ChristopherDavisUCI
Copy link
Contributor Author

Hmm, do you see what's wrong with the json that results from your example? At first glance I would have expected this json to be correct. Open the Chart in the Vega Editor

@mattijn
Copy link
Contributor

mattijn commented Oct 9, 2022

Nope, reported here: vega/vega-lite#8452. Including a grouped issue regarding all the issues we have for the repeat operator, vega/vega-lite#8453.

@mattijn
Copy link
Contributor

mattijn commented Oct 12, 2022

I discovered two more issues that are not working:

First, .interactive() does not work in combination with h/v-concat:

!python -m pip install git+https://github.com/ChristopherDavisUCI/altair.git@liftparams
import altair as alt

source = 'https://unpkg.com/[email protected]/data/weather.csv'

# interval = alt.selection_interval(encodings=['x'], bind='scales')
line = (
    alt.Chart(height=100)
    .mark_bar(point=True)
    .encode(
        x=alt.X("date:T"),
        y=alt.Y("precipitation:Q"),
        color=alt.Color("location:N"),
    )
)
alt.vconcat(line, line, data=source).interactive(bind_y=False)  # .add_params(interval)
AttributeError: 'VConcatChart' object has no attribute 'interactive'

Second, I get a duplicate signal name error with the following:

highlight = alt.selection_point(
    nearest=True, on="mouseover", encodings=["x"], clear="mouseout"
)
interval = alt.selection_interval(encodings=['x'], bind='scales')

line = (
    alt.Chart(height=100)
    .mark_line(point=True)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),
        color=alt.Color("location:N"),
    )
)  # .interactive(bind_y=False)  # add_params(interval)

rule = (
    alt.Chart()
    .mark_rule()
    .encode(
        x=alt.X("month(date):T"),
        color=alt.value("black"),
        opacity=alt.condition(highlight, alt.value(1), alt.value(0), empty=False),
    )
)

tick = (
    alt.Chart()
    .mark_tick(point=True)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),
        color=alt.Color("location:N"),
    )
)

alt.vconcat(line, tick + rule, data=source).add_params(
    highlight
)
Javascript Error: Duplicate signal name: "param_45_tuple"
This usually means there's a typo in your chart specification. See the javascript console for the full traceback.

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks @mattijn I will check those out! I always appreciate these bug examples.

By the way, it's slightly easier for me when you use the "url" data syntax, because then the json that's created is much more manageable. So if it's ever easy to make that switch, please do!

@mattijn
Copy link
Contributor

mattijn commented Oct 12, 2022

Will do!

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks for changing the data! I will try to understand the syntax so I can do that myself in the future.

Are we sure vconcat and hconcat should have an interactive method? I looked back to v3 and I see interactive defined for Chart, LayerChart, FacetChart, and RepeatChart but not VConcatChart.

@mattijn
Copy link
Contributor

mattijn commented Oct 12, 2022

For me it make sense and the VL-scheme is OK with it. If defined on the concat level, the axis interaction will be done on both charts:

Open the Chart in the Vega Editor

This is different compare to when defining on each sub-chart (which works already):

Open the Chart in the Vega Editor

Even with unequal axis name and type, this is OK on the concat: Open the Chart in the Vega Editor

BTW, it's just a shortcut to the parameter variant (which works already):

interval = alt.selection_interval(encodings=['x'], bind='scales')
line = (
    alt.Chart(height=100)
    .mark_bar(point=True)
    .encode(
        x=alt.X("date:T"),
        y=alt.Y("precipitation:Q"),
        color=alt.Color("location:N"),
    )
)
alt.vconcat(line, line, data=source).add_params(interval)  # .interactive(bind_y=False)

For the second example regarding the duplicate signal, I think we had this issue before.
If I change .mark_line(point=True) to .mark_line(point=False) it works. See vega/vega-lite#7854, but that Altair spec it refers to does work now already.. (#2528 (comment))

@ChristopherDavisUCI
Copy link
Contributor Author

Okay cool, should be no problem to add that interactive functionality then... just wanted to confirm that it wasn't something broken by this PR.

I haven't taken a look at the second example yet but will soon.

The interaction is bound between the charts (as opposed to another possibility, where the interaction would be added to each constituent chart separately).
@ChristopherDavisUCI
Copy link
Contributor Author

Hi @mattijn, could you please check and see if the concat interactive method is now working as you expected?

Regarding your second example, to me (maybe this is the same as you wrote) it seems like this is an issue on the Vega-Lite side, not the Altair side? Or at least I thought this kind of parameter use was allowed. (As a mnemonic, I believe your example has the form alt.vconcat(view_1, alt.layer(view_2, view_3)) and we have a parameter on the top level with views=[view_1, view_2]. I don't see why that would not be allowed.) Does that match your understanding?

@mattijn
Copy link
Contributor

mattijn commented Oct 13, 2022

Yes, that works great!

For the second chart, if I do:

alt.vconcat(line, (tick + rule).add_params(highlight), data=source)

it does work. But if I also add a highlight condition to the line then I run into issues again. There is some peculiarity with point=True in VL indeed. Upon manually defining a mark_circle in combination with a mark_line without point=True, our introduced logic does work as expected:

source = "https://unpkg.com/[email protected]/data/weather.csv"
highlight = alt.selection_point(
    name="hover",
    on="mouseover",
    nearest=True,
    encodings=["x"],
    empty=False,
    clear="mouseout",
)

top_base = alt.Chart(height=100, width=200).encode(
    x=alt.X("month(date):T"),
    y=alt.Y("mean(precipitation):Q"),
    color=alt.condition(highlight, alt.Color("location:N"), alt.value("gray")),
)

line = top_base.mark_line()
circle = top_base.mark_circle(size=100)


rule = (
    alt.Chart(height=100, width=200)
    .mark_rule(size=6)
    .encode(
        x=alt.X("month(date):T"),
        color=alt.value("black"),
        opacity=alt.condition(highlight, alt.value(1), alt.value(0)),
    )
)

tick = (
    alt.Chart()
    .mark_tick(thickness=5)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),
        color=alt.Color("location:N"),
    )
)

alt.vconcat((line + circle), (tick + rule), data=source).add_params(highlight)

Let's leave it at that for now.


One more question regarding docstrings, probably better for another PR, but I will still mention it.

Currently the docstrings for some new introduced parameter methods are rather limited:
image

Where in the above example I've defined it as such:

highlight = alt.selection_point(
    name="hover",
    on="mouseover",
    nearest=True,
    encodings=["x"],
    empty=False,
    clear="mouseout",
)

How can one know about this without docstrings?

@mattijn
Copy link
Contributor

mattijn commented Oct 13, 2022

Let me create an issue on the docstrings and the current limitation on repeat within the altair repo and then we can wait here until altair-viz/altair_viewer#51 is merged so the Github Actions in this PR can be properly do their jobs (cc: @jakevdp).

@ChristopherDavisUCI
Copy link
Contributor Author

Hi @mattijn, do you know, what is the analogue of "child__row_petalLength" when there is both a row and a column repeater? I think I tried "child__row_petalLength_column_sepalLength", "child__row_petalLength__column_sepalLength" and "child__row_petalLengthchild__column_sepalLength", but as far as I can tell, none of those works.

@mattijn
Copy link
Contributor

mattijn commented Oct 22, 2022

It is child__row_petalLengthcolumn_sepalLength.

I modified the last chart under this section from the VL-docs here https://vega.github.io/vega-lite/docs/bind.html#scale-binding as an example, see: Open the Chart in the Vega Editor.
I'm not sure what happens if the column include spaces and/or other strange symbols. Probably requires escaping?

@ChristopherDavisUCI
Copy link
Contributor Author

Thanks as always @mattijn!

I might start with a fresh PR once things seem to be working, but I think the latest commit has the repeat names working for plain repeats as well as repeats specifying "row" and/or "column". (Should we be supporting anything else, like alt.repeat(layer=???)?)

@mattijn Can you work your usual magic and find charts that are not behaving as expected?

Is the following supposed to work? It's not at the moment. It produces this Chart in the Vega Editor

import altair as alt

source = 'https://unpkg.com/[email protected]/data/weather.csv'

highlight = alt.selection_point(
    nearest=True, on="mouseover", encodings=["x"], clear="mouseout"
)
interval = alt.selection_interval(encodings=['x'], bind='scales')

line = (
    alt.Chart(height=100)
    .mark_line(point=True)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),
        color=alt.Color("location:N"),
    )
)  # .interactive(bind_y=False)  # add_params(interval)

rule = (
    alt.Chart()
    .mark_rule()
    .encode(
        x=alt.X("month(date):T"),
        color=alt.value("black"),
        opacity=alt.condition(highlight, alt.value(1), alt.value(0), empty=False),
    )
)

tick = (
    alt.Chart()
    .mark_tick(point=True)
    .encode(
        x=alt.X("month(date):T"),
        y=alt.Y("mean(precipitation):Q"),
        color=alt.Color("location:N"),
    )
)

alt.vconcat(line, tick + rule, data=source).add_params(
    highlight
)

@mattijn
Copy link
Contributor

mattijn commented Oct 23, 2022

Your last spec won't work as was concluded in #2684 (comment).

This spec:

import altair as alt
from vega_datasets import data

source = data.movies.url

alt.Chart(source).mark_line().encode(
    x=alt.X(alt.repeat("column"), bin=True),
    # x=alt.X("IMDB_Rating:Q", bin=True),
    y=alt.Y(
        alt.repeat("layer"), aggregate="mean", title="Mean of US and Worldwide Gross"
    ),
    color=alt.ColorDatum(alt.repeat("layer")),
).repeat(
    layer=["US_Gross", "Worldwide_Gross"],
    column=["IMDB_Rating", "Rotten_Tomatoes_Rating"],
)  # .interactive()

Gives:

ValueError: layer argument cannot be combined with row/column argument.

While it is allowed in VL: Open the Chart in the Vega Editor. Technically not related to this PR though.

I cannot test what the behaviour of .interactive() should do, since this errors with a duplicate signal name on the VL side: Open the Chart in the Vega Editor, probably fixed by vega/vega-lite#8486.

This spec also gives the same error on duplicate signals:

#import altair as alt
source = 'https://unpkg.com/[email protected]/data/weather.csv'

highlight = alt.selection_point(
    nearest=True, on="mouseover", encodings=["x"], clear="mouseout"
)
rule = (
    alt.Chart()
    .mark_rule()
    .encode(
        x=alt.X(alt.repeat('row'), bin=True),
        color=alt.value("black"),
        opacity=alt.condition(highlight, alt.value(1), alt.value(0), empty=False),
    )
)

line = (
    alt.Chart()
    .mark_line(point=True)
    .encode(
        x=alt.X(alt.repeat('row'), bin=True),
        y=alt.Y(alt.repeat('column'), bin=True),
        color=alt.Color("location:N"),
    )
)

alt.layer(line, rule, data=source, height=200, width=200).add_params(
    highlight
).repeat(column=["precipitation", "wind"], row=["temp_max", "precipitation"])#.to_dict()

But changing the order or line and rule in the alt.layer it does work (alt.layer(rule, line, ...))...

The tests I covered so far: https://colab.research.google.com/drive/16oqde86OsNFBtVpa4x0p7yMEyWKcUcAP?usp=sharing

I think we are done here.

@ChristopherDavisUCI
Copy link
Contributor Author

Awesome, thanks again @mattijn.

I'm hoping to create a new PR so I can clean up some of the logic/ordering of the commits.

@ChristopherDavisUCI
Copy link
Contributor Author

Closing this in favor of #2702.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants