-
Notifications
You must be signed in to change notification settings - Fork 795
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
how to add legend in basic charts #3289
Comments
Or as is mentioned in the same vega/vega-lite#3411 (comment),
Than this could/should work: # alt.Color(datum='score').scale(range=['lightgray'])
alt.ColorDatum('score').scale(range=['lightgray']) But this returns currently in an error stating that AttributeError: 'ColorDatum' object has no attribute 'scale' |
I'm generally in favor of adding the encoding channel options methods to the datum classes (and the value classes? or would they not be needed/relevant there?). I think that would make them consistent with how the channels ( I would like to avoid adding something like a |
You are right that this cannot work with Btw: This sets color (without control on legend): alt.Color(value='lightgray') This adds a legend (without control on actual color) alt.Color(datum='score') But combining them errors: alt.Color(value='lightgray', datum='score') |
It would be nice to allow for alt.Color(datum='score').scale(...) But it seems like we run into the same error as in #2913 (comment) |
Setting the color can be done with
|
On first glance, it seems to me that the issue arises as the original dataframe is not in a proper long format. Hence, you're trying to do a color scale across columns and then have to manually encode it. If you reshape the dataframe, the spec gets easier: source_long = source.melt("project", var_name="variable", value_name="value")
base = alt.Chart(source_long).encode(
x="project",
y="value",
color=alt.Color("variable:N").scale(
domain=["score", "goal"], range=["lightgray", "green"]
),
)
base.mark_bar().transform_filter(alt.datum.variable == "score") + base.mark_tick(
thickness=3
).transform_filter(alt.datum.variable == "goal") Somewhat unrelated but to also adjust the legend symbols, one could do either: scale_kwargs = dict(domain=["score", "goal"], range=["lightgray", "green"])
base = alt.Chart(source_long).encode(
x="project",
y="value",
stroke=alt.Stroke("variable:N", scale=alt.Scale(**scale_kwargs)),
color=alt.Color("variable:N")
.scale(**scale_kwargs)
.legend(
symbolType=alt.expr(alt.expr.if_(alt.datum.label == "goal", "stroke", "square"))
),
)
base.mark_bar().transform_filter(
alt.datum.variable == "score"
) + base.mark_tick().transform_filter(alt.datum.variable == "goal") Using stroke as well to encode the color is necessary as else the base = alt.Chart(source_long).encode(
x="project",
y="value",
color=alt.Color("variable:N")
.scale(domain=["score", "goal"], range=["lightgray", "green"])
.legend(
symbolType=alt.expr(
alt.expr.if_(alt.datum.label == "goal", "stroke", "square")
),
symbolStrokeColor=alt.expr(
alt.expr.if_(alt.datum.label == "goal", "green", "lightgray")
),
),
)
base.mark_bar().transform_filter(
alt.datum.variable == "score"
) + base.mark_tick().transform_filter(alt.datum.variable == "goal") |
Given a basic chart:
That is defined as follows:
How can I add a legend to clarify the used colors? Like this:
Currently this requires me to define an Altair specification as such:
In my honest opinion, I think this is too much to ask from a user perspective.
I can understand we are bound by the Grammar of Graphics and I found this vega/vega-lite#3411 (comment) in the Vega-Lite repository on forcing legends.
Without upsetting people, I feel we have to rethink the GoG in this regard. I do not feel going against the GoG if a syntax as such could be supported:
I'm also open to other approaches that are easier to implement than the current working spec above.
The text was updated successfully, but these errors were encountered: