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

Move shared encodings of layered charts to top level? #2999

Open
joelostblom opened this issue Mar 27, 2023 · 2 comments
Open

Move shared encodings of layered charts to top level? #2999

joelostblom opened this issue Mar 27, 2023 · 2 comments

Comments

@joelostblom
Copy link
Contributor

I opened this as a feature request, but maybe it is more of a discussion as a follow up to #2991. The overall sentiment is whether Altair should simplify redundancy in layered specs by moving common encodings to the top level of the Chart instead of repeating them in each layer. I think this is low priority as it would not change any functionality when working in Altair, just the verbosity of the VL spec.

Currently, if we create an Altair spec like this, the code suggests that the encodings are part of the top level chart (base) and shared between the marks:

import altair as alt
from vega_datasets import data

base = alt.Chart(data.wheat.url).encode(
    x='wheat:Q',
    y="year:O",
    text='wheat:Q'
)
base.mark_bar() + base.mark_text(align='left', dx=1)

However, what actually happens is that the encodings are redundantly copied into the mark of each layer in the Vega-Lite spec:

{
  "layer": [
    {
      "mark": {"type": "bar"},
      "encoding": {
        "text": {"field": "wheat", "type": "quantitative"},
        "x": {"field": "wheat", "type": "quantitative"},
        "y": {"field": "year", "type": "ordinal"}
      }
    },
    {
      "mark": {"type": "text", "align": "left", "dx": 1},
      "encoding": {
        "text": {"field": "wheat", "type": "quantitative"},
        "x": {"field": "wheat", "type": "quantitative"},
        "y": {"field": "year", "type": "ordinal"}
      }
    }
  ],
  "data": {
    "url": "https://cdn.jsdelivr.net/npm/[email protected]/data/wheat.json"
  }
}

A more suitable translation would be to include a top-level encoding that can be shared by all the layered marks. This leads to a less verbose Vega-Lite spec that is more semantically similar to how the code is written in Altair:

{
  "encoding": {
    "text": {"field": "wheat", "type": "quantitative"},
    "x": {"field": "wheat", "type": "quantitative"},
    "y": {"field": "year", "type": "ordinal"}
  },
  "layer": [
    {"mark": {"type": "bar"}},
    {"mark": {"type": "text", "align": "left", "dx": 1}}
  ],
  "data": {
    "url": "https://cdn.jsdelivr.net/npm/[email protected]/data/wheat.json"
  }
}

That VL spec can actually be generated in Altair if we use LayerChart directly:

alt.LayerChart(
    data=data.wheat.url,
    encoding=alt.SharedEncoding(
        x=alt.X('wheat:Q'),
        y=alt.Y('year:O'),
        text=alt.Text('wheat:Q')
    ),
    layer=[
        alt.Chart().mark_bar(),
        alt.Chart().mark_text(align='left', dx=2)
    ]
    
)

I wonder if Altair should try to figure out which encodings are shared between layers and can be moved to the top-level? There is not that much practical benefit from this as the encodings in Altair's grammar can still be thought of conceptually as belonging to the chart and shared by each mark that is added to the chart (even when the code is written as in the first example, it is just that this is not how it works under the hood). I am not sure if there are situations where this automatic move would be undesired.

@mcp292
Copy link

mcp292 commented Mar 27, 2023

As a user, I really like this syntax. As a user, this discussion may not require my opinion.

@mattijn
Copy link
Contributor

mattijn commented Apr 27, 2023

A bit related and a bit off-topic, but interesting nonetheless: queryverse/VegaLite.jl#411.

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

No branches or pull requests

3 participants