# How to get the bin values from a Plot?

**URL:** <https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090>\
**Category:** Help\
**Created:** [July 13, 2023, 12:47pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090 "2023-07-13T12:47:09Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![nachocab](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nachocab/32/2426_2.png) [@nachocab](https://talk.observablehq.com/u/nachocab)\
**Post date:** [July 13, 2023, 12:47pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/1 "2023-07-13T12:47:10Z")

</div>

When I apply a bin transform, I know I can access the elements of each bin from the outputs object [as shown in this plot](https://observablehq.com/@observablehq/plot-highlighted-bin):

```js
Plot.rectY(
  olympians,
  Plot.binX(
    {
      y: "count",
      fill: (bin) => bin.some(d => d.name === "Aaron Brown")
    },
    { x: "weight" }
  )
)

```

If I just want to draw a line at the median frequency across all bins, like [in this histogram](https://observablehq.com/@observablehq/plot-stargazer-history#cell-246), I can use groupZ and set x, x1, and x2 to undefined (although I’m not yet sure why that works 😅):

```js
 Plot.ruleY(data, {
  ...Plot.groupZ(
    { y: "median" },
    Plot.binX(
      { y: "count" },
      {
        x: "date",
        // strokeDasharray: [5, 10],
        // strokeWidth: 0.25,
        thresholds: 100
      }
    )
  ),
  x: undefined,
  x1: undefined,
  x2: undefined
})

```

But what if I want to get the actual bins to use them in a different cell?

If I can’t extract them from the plot, I thought I could do it manually, but I must be doing something wrong because I don’t get the right value (I get 20 instead of 14):

 ![CleanShot 2023-07-13 at 15.02.44@2x](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/f/fb8cec98681cd92a65bfd2f929f282f1f2b07c4e.png)

```js
d3.median(
  d3
    .bin()
    .value((d) => d.date)
    .thresholds(100)(data),
  (d) => d.length
) // 20

```

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [July 13, 2023, 1:48pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/2 "2023-07-13T13:48:03Z")

</div>

A reason might be because d3.bin is not using temporal bins, so all the dates are converted to numbers (milliseconds since EPOCH), and that is what gets binned?

---

<div class="post-metadata">

**Author:** ![nachocab](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nachocab/32/2426_2.png) [@nachocab](https://talk.observablehq.com/u/nachocab)\
**Post date:** [July 13, 2023, 3:00pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/3 "2023-07-13T15:00:37Z")

</div>

It could be. I tried your thresholdTime suggestion, but I still get a different median:

 ![CleanShot 2023-07-13 at 17.00.01@2x](https://canada1.discourse-cdn.com/flex030/uploads/observablehq/original/2X/c/c255e19055f84515e8949ee95b5aa3614cd159b6.png)

> [@nachocab](#):
>
> But what if I want to get the actual bins to use them in a different cell?

Is this not possible, then?

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [July 13, 2023, 4:04pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/4 "2023-07-13T16:04:51Z")

</div>

Can you share a notebook with your experiment and expected results?

> Is this not possible, then?

I haven’t said that 🙂

Plot is not meant for that, but the mark’s _initialize_ method is the one that computes these channels.

---

<div class="post-metadata">

**Author:** ![nachocab](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nachocab/32/2426_2.png) [@nachocab](https://talk.observablehq.com/u/nachocab)\
**Post date:** [July 13, 2023, 4:32pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/5 "2023-07-13T16:32:12Z")

</div>

> [@Fil](#):
>
> Can you share a notebook with your experiment and expected results?

[Here you go](https://observablehq.com/d/0b3b49271111019d). I was just modifying the stargazer notebook.

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [July 13, 2023, 10:02pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/6 "2023-07-13T22:02:07Z")

</div>

To get 14, you need to ignore the empty bins:

```auto
d3.median(
  d3
    .bin()
    .value((d) => d.date)
    .thresholds(thresholdTime(100))(data),
  (d) => d.length || NaN 
)

```

If you call:

```auto
init = Plot.rectY(
  data,
  Plot.binX({ y: "count" }, { x: "date", thresholds: 100 })
).initialize()

```

you can then inspect the bins in init.data, and their bounds in init.channels.x1.value and init.channels.x2.value

---

<div class="post-metadata">

**Author:** ![nachocab](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nachocab/32/2426_2.png) [@nachocab](https://talk.observablehq.com/u/nachocab)\
**Post date:** [July 14, 2023, 5:47am UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/7 "2023-07-14T05:47:42Z")

</div>

That’s super useful! Thanks, Fil. I also found your excellent notebook where you go deeper on this:

> **[Read channels initialized by a Plot mark](https://observablehq.com/@observablehq/read-channels-initialized-by-a-plot-mark)**
>
> Re: https://talk.observablehq.com/t/using-plot-for-data-refinement-only/6722 Here’s a mark: We can initialize it to retrieve the channels that Plot has derived from the data: Let’s wrap this into an inspectMark function, which returns two tables;...

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [July 14, 2023, 8:39am UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/8 "2023-07-14T08:39:14Z")

</div>

Thanks! I had forgotten about it 🙂

---

<div class="post-metadata">

**Author:** ![nachocab](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/nachocab/32/2426_2.png) [@nachocab](https://talk.observablehq.com/u/nachocab)\
**Post date:** [August 15, 2023, 5:47pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/9 "2023-08-15T17:47:27Z")

</div>

@Fil I’m having trouble with a more complex example.

I’ve been able to get the [bin values from plot](https://observablehq.com/@nachocab/pitfalls-when-using-plot-rect#cell-202), but I’m not able to get the same bins when [using `d3.bin`](https://observablehq.com/@nachocab/pitfalls-when-using-plot-rect#cell-278).

EDIT: Okay, [I figured it out](https://observablehq.com/@nachocab/pitfalls-when-using-plot-rect#cell-311). But I’m still wondering if there’s a simpler way. 😅

---

<div class="post-metadata">

**Author:** ![Fil](https://yyz2.discourse-cdn.com/flex030/user_avatar/talk.observablehq.com/fil/32/207_2.png) [@Fil](https://talk.observablehq.com/u/Fil)\
**Post date:** [August 15, 2023, 6:20pm UTC](https://talk.observablehq.com/t/how-to-get-the-bin-values-from-a-plot/8090/10 "2023-08-15T18:20:34Z")

</div>

to answer

```js
new Date("1854-01-01"), // how can I not hardcode this?

```

you should probably use:

```js
d3.utcMonth.every(4).floor(d3.min(crimea, (d) => d.date))

```

(Time intervals are hard, in any case)
