1

How can you retrieve and display the values used to compute the high of binned bars in a vega histogram?

In this d3 observable notebook I illustrate what want to achieve... When a bar is clicked, I update the selected_text variable with the bar's underlying values which were counted to give the bar's high.

The related question deals with the fold transform but in my case, I am looking for the inverse of the flatten transform.

Here is an illustration of the data transformation I am looking for. Going from:

[
    {"name": "alpha", "data": 123, "bin0": 1, "bin1": 2},
    {"name": "alpha", "data": 789, "bin0": 2, "bin1": 3},
    {"name": "beta",  "data": 456, "bin0": 2, "bin1": 3},
    {"name": "beta",  "data": 789, "bin0": 3, "bin1": 4},
    {"name": "beta",  "data": 0AB, "bin0": 3, "bin1": 4}
]

to

[
    "bin0": 1, "bin1": 2, values: [{"name": "alpha", "data": 123}]
    "bin0": 2, "bin1": 3, values: [{"name": "alpha", "data": 789},
                   {"name": "beta", "data": 456}]
    "bin0": 3, "bin1": 4, values: [{"name": "beta", "data": 789},
                   {"name": "beta", "data": 0AB}]
]

I think this could be achieved if the concat expression was available to the groupby operator of the aggregation transforms, but it is not.

Malik Koné
  • 635
  • 1
  • 7
  • 16
  • This question lacks focus, and so it is very difficult to understand what exactly you are asking. See [How To Ask](https://stackoverflow.com/help/how-to-ask) for help on how to ask questions that are more likely to get an answer. – jakevdp Mar 17 '20 at 19:25
  • I reformulated. Thank you for your comment. – Malik Koné Mar 17 '20 at 20:36

2 Answers2

2

The "unflatten" transform can be roughly achieved using an aggregate transform with the values aggregate:

{
  "data": {
    "values": [
      {"name": "alpha", "data": 123, "bin0": 1, "bin1": 2},
      {"name": "alpha", "data": 789, "bin0": 2, "bin1": 3},
      {"name": "beta", "data": 456, "bin0": 2, "bin1": 3},
      {"name": "beta", "data": 789, "bin0": 3, "bin1": 4},
      {"name": "beta", "data": 789, "bin0": 3, "bin1": 4}
    ]
  },
  "transform": [
    {
      "aggregate": [{"op": "values", "as": "values"}],
      "groupby": ["bin0", "bin1"]
    }
  ],
  "mark": "point"
}

In the data viewer of the Vega Editor, you can see that the transformed data are:

[
  {"bin0": 1, "bin1": 2,
   "values": [{"name": "alpha", "data": 123, "bin0": 1, "bin1": 2}]},
  {"bin0": 2, "bin1": 3,
   "values": [{"name": "alpha", "data": 789, "bin0": 2, "bin1": 3},
              {"name": "beta", "data": 456, "bin0": 2, "bin1": 3}]},
  {"bin0": 3, "bin1": 4,
   "values": [{"name": "beta", "data": 789, "bin0": 3, "bin1": 4},
              {"name": "beta", "data": 0AB, "bin0": 3, "bin1": 4}]}
]
jakevdp
  • 77,104
  • 11
  • 125
  • 160
  • Ok, that's my answer. but it spring another one that I should ask in the meta section maybe. What you mention is not documented. There is not `unflatten` operator. Since I have not other teacher than people over Internet, how could I have found out this by myself in two month of research ? You will probably answer, explore. but There is so much to explore now days, that another question is how to know where to explore... because I did explore in this last 2 months, coming up with my own d3 facet version. but still I wish I would not reinvent 'a bad' wheel too often. – Malik Koné Mar 17 '20 at 21:47
  • 1
    I'm not sure what to suggest, but for what it's worth, the reason I knew about this is because of a side-project where I implemented most of the vega-lite transform grammar in Python: https://github.com/altair-viz/altair-transform – jakevdp Mar 17 '20 at 22:03
  • Thank you. It's encouraging to see that what I don't know but tried to know is not that easy to know. I mean not many people translate the vega-lite transform grammar in another language. – Malik Koné Mar 17 '20 at 22:16
0

Given Jake's answer, here is a complete example in Vega of what I was aiming for.

{
  "$schema": "https://vega.github.io/schema/vega/v5.json",
  "description": "A histogram of film ratings, modified to include null values.",
  "width": 400,
  "height": 200,
  "padding": 5,
  "autosize": {"type": "fit", "resize": true},
  "signals": [
    {"name": "binCount", "update": "(bins.stop - bins.start) / bins.step"},
    {"name": "barStep", "update": "(width ) / (1 + binCount)"},
            {
      "name": "tooltip",
      "value": {},
      "on": [
        {"events": "rect:mouseover", "update": "slice(datum.dlist,0,2)"},
        {"events": "rect:mouseout",  "update": "{}"}
      ]
    }
  ],
  "data": [
    {
      "name": "table",
      "values": [
        {"name": "alpha", "data": "123"},
        {"name": "alpha", "data": "789"},
        {"name": "beta", "data": "456"},
        {"name": "beta", "data": "789"},
        {"name": "gamma", "data": "789"},
        {"name": "beta", "data": "300"}
      ],
      "transform": [
        {"type": "extent", "field": "data", "signal": "extent"},
        {
          "type": "bin",
          "signal": "bins",
          "field": "data",
          "extent": {"signal": "extent"},
          "maxbins": 4
        }
      ]
    },
      {
      "name": "aggregat",
      "source": "table",
      "transform": [
        {
          "type": "aggregate",
          "groupby": ["bin0", "bin1"],
          "ops": ["values"],
          "fields": ["undefined"],
          "as": ["values"]
        }

      ]
    },
    {
      "name": "counts",
      "source": "table",
      "transform": [{"type": "aggregate", "groupby": ["bin0", "bin1"]},
       {
          "type": "lookup",
          "from": "aggregat",
          "key": "bin0",
          "fields": ["bin0"],
          "values": ["values"],
          "as": ["dlist"]
        }]
    }
  ],
  "scales": [
    {
      "name": "yscale",
      "type": "linear",
      "range": "height",
      "round": true,
      "nice": true,
      "domain": {"fields": [{"data": "counts", "field": "count"}]}
    },
    {
      "name": "xscale",
      "type": "linear",
      "range": [{"signal": "barStep "}, {"signal": "width"}],
      "round": true,
      "domain": {"signal": "[bins.start, bins.stop]"},
      "bins": {"signal": "bins"}
    }
  ],
  "axes": [
    {"orient": "bottom", "scale": "xscale", "tickMinStep": 0.5},
    {"orient": "left", "scale": "yscale", "tickCount": 5, "offset": 5}
  ],
  "marks": [
    {
      "type": "rect",
      "from": {"data": "counts"},
      "encode": {
        "update": {
                    "tooltip" : { "signal": "tooltip"},
          "x": {"scale": "xscale", "field": "bin0", "offset": 1},
          "x2": {"scale": "xscale", "field": "bin1"},
          "y": {"scale": "yscale", "field": "count"},
          "y2": {"scale": "yscale", "value": 0},
          "fill": {"value": "steelblue"}
        },
        "hover": {"fill": {"value": "firebrick"}}
      }
    }
  ]
}
Malik Koné
  • 635
  • 1
  • 7
  • 16