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.67k stars 608 forks source link

Supporting labeling for all basic charts #64

Closed kanitw closed 3 years ago

kanitw commented 9 years ago

Just always put numbers outside like I add 28, 55 below (same for all bars — I’m just adding this by hand so I added only the first two.)

vega_editor

kanitw commented 8 years ago

@willium I actually start to think that this one might be a better to begin with. :)
Start with trying to see how to extend Vega spec first, more details about where do you have to extend the code will follow. We can chat more tomorrow evening or next week if you’re around as well.

domoritz commented 8 years ago

@kanitw just wondering what should happen if the bar goes all the way to the top. If the label is outside, we may have to change the layout.

Other than that, yes, this is a great issue for @willium.

kanitw commented 8 years ago

@domoritz That's a good corner case, but let will begin with putting it on the top / on the right first.

willium commented 8 years ago

@kanitw seems relatively straight forward -- To clarify, this is different than a tooltip in that you want the text to always show above all bars (or on the sides depending on orient) without hover. Essentially an extension of https://github.com/vega/vega/wiki/Tutorial#bar-chart-specification and the code that makes that work for vega-lite as well. So:

@domoritz This text overflow case seems to be broken in the vega example https://github.com/vega/vega/wiki/Tutorial#bar-chart-specification as well overflow text

kanitw commented 8 years ago

@willium yep. You're right. It's basically should be the same as "label" shelf in Tableau.

I think currently Vega does not have a way to add additional offset to the scale when drawing domain from data, but this feature might come in handy in this case and #374 By this I mean, if the data ranges from [0, 100] if we can add property like domain.upperBoundOffset and thus main the scale's domain become [0, 120]. That might be useful. But since we don't have it yet, let's not worry about it yet.

willium commented 8 years ago

Hey @kanitw @domoritz, so I just re-started on this. I have a vega example showing labels as text mark types, pretty straight forward: https://gist.github.com/willium/f3ffa817ac87f40c2e54.

Now moving on to the vega-lite: It seems like vega-lite has both text and label within channels (what's the difference semantically?), and vega-lite doesn't have many examples with multiple marks within one document, leading me to believe that's not intended as it is in vega. Would this be a channel encoding of the data with vega-lite? In this case I'm not sure what new features I'm inventing vs. how much I'm just building an example for an existing feature set. Are labels entirely unsupported by vega-lite as-is? Would love some more information/guidance to make sure I'm understanding the issue at hand entirely.

domoritz commented 8 years ago

Excellent. The example looks great.

Labels are used inside axes. Labels refers to the annotations of axes that shows categories or values of a quantitative domain. The text channel is to draw text marks that are driven by the rows is the data (labels are driven by the domain of the data). For the bar labels (for lack of a better term, maybe annotations), you created another text mark with similar properties as the rect mark.

Vega-lite has a text channel and a text mark. Right now the text channel only works for the text mark (you use that when you create a table). So for implementing the labels, we have two options.

First, there could be a annotation: true | false option on the field def or in the config. Second, we could add a labek channel for labels/annotations for bar charts (and also scatter plots later). For example

{
  "mark": "bar",
  "encoding": {
    "x": {"field": "Origin","type": "nominal"},
    "y": {
      "field": "Horsepower",
      "type": "quantitative",
      "aggregate": "mean"
    },
    "label": {
      "field": "Horsepower",
      "type": "quantitative",
      "aggregate": "mean"
    }
  },
  "data": {"url": "data/cars.json"}
}

The second option is more flexible because you could have other data driving the annotation/ label but also repetitive for the common case. However, let's implement the general case first and then add a shorthand.

@kanitw Why did you suggest to add a new label channel rather than using the existing text channel? I couldn't think of a case where we we need both cases.

Whenever we add a feature to vega-lite, we have to think about how we design the API. It usually helps me to think about how I would expect the API to look like for specific cases and see what the best general case is. If you want, you can sketch a few json objects and post them here and we can give you feedback.

kanitw commented 8 years ago

@willium

Are labels entirely unsupported by vega-lite as-is? Would this be a channel encoding of the data with vega-lite?

Yes. It is not supported yet, but I have recently added some scaffolding for the new label channel in #885.

When a label channel is used, we need to add another vega marks group (as done in the scaffold here. Once each <mark type's namespace>.labels(model) property returns a mark properties for the label mark group (which would be a Vega text mark), then label would be supported.

In this case I'm not sure what new features I'm inventing vs. how much I'm just building an example for an existing feature set.

For this issue, you would need to fill bar.labels(model) in compiler/marks.ts. (You can see that I put TODO(#64).)


Note for @domoritz's comment:

Labels refers to the annotations of axes that shows categories or values of a quantitative domain. This definition refers to "axis labels", not labels in general. In this issue, we are talking about labels of bar marks.

@kanitw Why did you suggest to add a new label channel rather than using the existing text channel? I couldn't think of a case where we we need both cases.

We never need both but they are semantically different. I was thinking about whether to use text to represent label too, but after careful consideration they are not the same thing and thus shouldn't use the same name.

Semantically, there are differences between (1) Mapping a field to text channel in text mark. This modifies property of the main mark group. Semantically, this is the text of the text mark, not its label. (2) adding marks label to other marks such as bar. This is not a text encoding because a bar should not have text by default, unless it's a label of the bar. When applied, this also adds a new Vega mark group with mark type (text), which semantically serves as label of the marks.

First, there could be a annotation: true | false option on the field def or in the config. Second, we could add a labek channel for labels/annotations for bar charts (and also scatter plots later).

We are obviously going for the second here. I don't know if we even need the first one, which is just a syntactic sugar.

Right now the text channel only works for the text mark.

With this design, text mark is the only mark type that contains text and therefore should remain the only mark that supports text channel.

willium commented 8 years ago

Hey, in will/bar-label I was able to get close to desired behavior (tested with https://gist.github.com/willium/3e09be5fbf8bbfbc972e). A few more values are hardcoded in than I'm comfortable with (mult w/ dy doesn't work, the offsets, and color). Also didn't get a chance yet to look at #374/domain.upperBoundOffset (as you mentioned @kanitw).

kanitw commented 8 years ago

Note: an early attempt for this was in PR #1406.

domoritz commented 5 years ago

Nice example: https://github.com/vis4/co2-history/

kanitw commented 5 years ago

Nice example: https://github.com/vis4/co2-history/

This also demonstrates another case that we need to support line breaks in Vega text marks too.

domoritz commented 3 years ago

We now have a labeling channel #7222