vega / vega-lite

A concise grammar of interactive graphics, built on Vega.
https://vega.github.io/vega-lite/
BSD 3-Clause "New" or "Revised" License
4.63k stars 601 forks source link

Encodings don't flow into child hconcat or vconcat specs #3780

Open davidanthoff opened 6 years ago

davidanthoff commented 6 years ago

I would have expected the following to work:

{
  "data": {"values": [{"a": 18,"b": 12.0},{"a": 15,"b": 11.5}]},
  "encoding": {
    "x": {"field": "a","type": "quantitative"},
    "y": {"field": "b","type": "quantitative"}
  },
  "vconcat": [
    {
      "mark": "point"
    },
    {
      "mark": "circle"
    }
  ]
}

Shouldn't the encodings from the top level spec be used in the two child specs inside the vconcat?

domoritz commented 6 years ago

As you remember, we had a long discussion about this in https://github.com/vega/vega-lite/issues/3384.

kanitw commented 6 years ago

Thanks for asking, but like @domoritz said, we previously discussed this and intentionally do not support it. https://github.com/vega/vega-lite/issues/3384#issuecomment-366096582

Some excerpts:

We intentionally constraint config to be at the top-level only to avoid multi-level config cascading, which makes it hard to implement correct behavior and also leads to confusing specs. So this may cause similar problems (but for encoding instead).

Another question is if layer support this, shouldn't vconcat and repeat support it too? (I would say no because it will definitely make it easier to cause the case for specs with multi-level nesting.) If we're to support this at all, I would only allow for layer.

marcprux commented 4 years ago

I'd like to make a case for re-opening this, at least as an enhancement request. Sometimes I want to compare side-by-side a number of different variations of transforms and aggregates. E.g.:

Screen Shot 2020-05-03 at 11 39 17

Currently, I need to manually copy all the encodings between the vconcat layers, like so:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.11.0.json",
  "data": {
    "values": [
      {"a": "A", "b": 28, "c": "X"},
      {"a": "B", "b": 55, "c": "Y"},
      {"a": "C", "b": 43, "c": "Z"},
      {"a": "D", "b": 91, "c": "X"},
      {"a": "E", "b": 81, "c": "Y"},
      {"a": "F", "b": 53, "c": "Z"},
      {"a": "G", "b": 19, "c": "X"},
      {"a": "H", "b": 87, "c": "Y"},
      {"a": "I", "b": 52, "c": "Z"}
    ]
  },
  "vconcat": [
    {
      "mark": "bar",
      "height": 50,
      "encoding": {
        "x": {"field": "c", "type": "ordinal"},
        "color": {"field": "a", "type": "nominal"},
        "y": {"field": "b", "type": "quantitative", "aggregate": "sum"}
      }
    },
    {
      "mark": "bar",
      "height": 50,
      "encoding": {
        "x": {"field": "c", "type": "ordinal", "axis": {"labelAngle": 0}},
        "color": {"field": "a", "type": "nominal"},
        "y": {"field": "b", "type": "quantitative", "aggregate": "count"}
      }
    },
    {
      "mark": "bar",
      "height": 50,
      "encoding": {
        "x": {"field": "c", "type": "ordinal", "axis": {"labelAngle": 0}},
        "color": {"field": "a", "type": "nominal"},
        "y": {"field": "b", "type": "quantitative", "aggregate": "median"}
      }
    }
  ]
}

It would make for much more fluid data exploration if I could just do this instead:

{
  "$schema": "https://vega.github.io/schema/vega-lite/v4.11.0.json",
  "data": {
    "values": [
      {"a": "A", "b": 28, "c": "X"},
      {"a": "B", "b": 55, "c": "Y"},
      {"a": "C", "b": 43, "c": "Z"},
      {"a": "D", "b": 91, "c": "X"},
      {"a": "E", "b": 81, "c": "Y"},
      {"a": "F", "b": 53, "c": "Z"},
      {"a": "G", "b": 19, "c": "X"},
      {"a": "H", "b": 87, "c": "Y"},
      {"a": "I", "b": 52, "c": "Z"}
    ]
  },
  "mark": "bar",
  "height": 50,
  "encoding": {
    "x": {"field": "c", "type": "ordinal"},
    "color": {"field": "a", "type": "nominal"}
  },
  "vconcat": [
    {
      "encoding": {
        "y": {"field": "b", "type": "quantitative", "aggregate": "sum"}
      }
    },
    {
      "encoding": {
        "y": {"field": "b", "type": "quantitative", "aggregate": "count"}
      }
    },
    {
      "encoding": {
        "y": {"field": "b", "type": "quantitative", "aggregate": "median"}
      }
    }
  ]
}
domoritz commented 4 years ago

I think our plan is to support this pattern with repeat instead. Yes, right now repeat only supports fields but eventually, it can support more. We recently refactored repeat so that it's just a preprocessing step. The advantage of repeat over your approach is that you can easily repeat in two dimensions.

Having said that, I can see value to supporting floating encodings into concats since we do support it for layer so I don't see why concat is fundamentally different.

marcprux commented 4 years ago

One nice thing about being able to have an encoding in the parent is that configuration of shared components like legends can happen in a single parent location, rather than the current behavior of joining child legends into one (or more) legends based on their configuration.

Screen Shot 2020-05-04 at 00 13 44

Having more flexibility for repeat will be nice, but it can't be used when you need to customizations the individual child layers separately.

domoritz commented 4 years ago

Since we went down and added support for flowing encodings into layers, and learned that it's really useful, I think it would make sense to also support it for concat and facet. How do you feel now @kanitw? Have your opinions changed since https://github.com/vega/vega-lite/issues/3384?

kanitw commented 4 years ago

I am more convinced to do so, but I'd rather do it after concat support shared axes and legends #2415, otherwise it will be pretty confusing.