vega-lite icon indicating copy to clipboard operation
vega-lite copied to clipboard

Composing cartesian and polar coordinates

Open jakevdp opened this issue 2 years ago • 5 comments

I was exploring some of the ideas outlined in this comment: https://github.com/vega/vega-lite/issues/408#issuecomment-500184377

I wanted to attempt a basic scatter chart in which each point is represented by a pie chart. Here's my basic attempt (open in editor):

{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {"category": 1, "value": 4, "x": 1, "y": 2},
      {"category": 2, "value": 6, "x": 1, "y": 2},
      {"category": 3, "value": 10, "x": 1, "y": 2},
      {"category": 4, "value": 3, "x": 1, "y": 2},
      {"category": 5, "value": 7, "x": 1, "y": 2},
      {"category": 6, "value": 8, "x": 1, "y": 2},
      {"category": 1, "value": 4, "x": 2, "y": 1},
      {"category": 2, "value": 6, "x": 2, "y": 1},
      {"category": 3, "value": 10, "x": 2, "y": 1},
      {"category": 4, "value": 3, "x": 2, "y": 1},
      {"category": 5, "value": 7, "x": 2, "y": 1},
      {"category": 6, "value": 8, "x": 2, "y": 1}
    ]
  },
  "mark": {"type": "arc", "radius": 15},
  "encoding": {
    "x": {"field": "x", "type": "quantitative", "scale": {"domain": [0, 3]}},
    "y": {"field": "y", "type": "quantitative", "scale": {"domain": [0, 3]}},
    "theta": {"field": "value", "type": "quantitative"},
    "color": {"field": "category", "type": "nominal"},
    "detail": [{"field": "x"}, {"field": "y"}]
  }
}

visualization (79)

It's almost what I want, but the extents of each mark are computed from the whole dataset rather than from the in-group values. Is there an easy way to make the arc mark extents respect the grouping implied by the x and y encodings?

jakevdp avatar Dec 09 '21 18:12 jakevdp

I like this direction. I don't have a solution but I think what we need is to facet the data by x and y before computing the scale for theta. Maybe this could be done with faceting into layers (which we don't support right now) and/or an addition to resolve.

domoritz avatar Dec 09 '21 19:12 domoritz

@jakevdp How about this for a workaround? Obviously, native support in Vega-Lite would still be preferred for the sake of simplicity but I think these intermediate transforms also achieve your goals.

FYI, I changed some of your values so both pies were not identical.

Editor

image


{
  "$schema": "https://vega.github.io/schema/vega-lite/v5.json",
  "data": {
    "values": [
      {"category": 1, "value": 4, "x": 1, "y": 2},
      {"category": 2, "value": 6, "x": 1, "y": 2},
      {"category": 3, "value": 10, "x": 1, "y": 2},
      {"category": 4, "value": 3, "x": 1, "y": 2},
      {"category": 5, "value": 7, "x": 1, "y": 2},
      {"category": 6, "value": 8, "x": 1, "y": 2},
      {"category": 1, "value": 14, "x": 2, "y": 1},
      {"category": 2, "value": 16, "x": 2, "y": 1},
      {"category": 3, "value": 10, "x": 2, "y": 1},
      {"category": 4, "value": 3, "x": 2, "y": 1},
      {"category": 5, "value": 7, "x": 2, "y": 1},
      {"category": 6, "value": 8, "x": 2, "y": 1}
    ]
  },
  "transform": [
    {
      "window": [{"op": "sum", "field": "value", "as": "total"}],
      "frame": [null, null],
      "groupby": ["x"]
    },
    {"calculate": "datum.value/datum.total * 100", "as": "percent"},
    {
      "stack": "percent",
      "offset": "normalize",
      "as": ["v1", "v2"],
      "groupby": ["x"]
    },
    {"calculate": "datum.v1 * (2*PI)", "as": "t1"},
    {"calculate": "datum.v2* (2*PI)", "as": "t2"}
  ],
  "mark": {
    "type": "arc",
    "radius": 15,
    "theta": {"expr": "datum.t1"},
    "theta2": {"expr": "datum.t2"}
  },
  "encoding": {
    "x": {"field": "x", "type": "quantitative", "scale": {"domain": [0, 3]}},
    "y": {"field": "y", "type": "quantitative", "scale": {"domain": [0, 3]}},
    "color": {"field": "category", "type": "nominal"}
  }
}

PBI-David avatar May 27 '22 10:05 PBI-David

I think @kanitw was thinking about a simpler way to add normalization to Vega-Lite in general and it would be perfect for this application.

domoritz avatar May 31 '22 18:05 domoritz

Is there a way to get the area of each circle to be proportional to the sum of "value" fields of each slice that makes up that circle in PB-David's approach? I tried

"mark": {
  "type": "arc",
  "radius": {
    "field": "sqrt_total", 
    "type": "quantitative"
  },

with {"calculate": "sqrt(datum.total)", "as": "sqrt_total"} in transform section but it didn't work.

aslangencer avatar Apr 09 '24 10:04 aslangencer

@aslangencer - you don't need a calculate. Just change the radius to this:

"mark": { "type": "arc", "radius": {"expr": "sqrt(datum.total)"}, "theta": {"expr": "datum.t1"}, "theta2": {"expr": "datum.t2"} },

PBI-David avatar Apr 09 '24 17:04 PBI-David