Log Histogram of Category Counts

I’m trying to convert the counts for a histogram to use a log scale. I tried adding
type: "log", to my axis, which does indeed print a log scale, but then all my data disappears.

I found I can convert the data to log scale directly by using

Plot .groupY({x: d => Math10.log(d.length)}, ...

But that relabels the axis to the log of the values (i.e. between 0 and 3.5 instead of between 10 and 10,000). I was hoping for the horizontal bars to relate the log10 of the values while the x-axis would label a log scale indicating their actual values.

Notebook: Log Histogram Plot / Paul Glezen | Observable

With type:“log” the bars disappear because they start at 0 (which is sent to -Infinity).

A simple solution is to use type: "symlog" instead, but the symlog ticks are not really pretty and you might want to adjust them by hand.

Another solution is to remap 0 to 1 or 0.5:

type: "log",
transform: d => Math.max(.5, d)

This second solution works well. In my present case the minimum value is 15, so \log_{10} of the minimum is greater than 1; 0.5 works well as a threshold. In a more general case I could determine the minimum programmatically and set such a threshold dynamically.

I appreciate the help.

Since the length of the bars is not meaningful in this case (as it requires picking an arbitrary baseline), you could also consider switching to a dot mark instead like so:

Plot.plot({
  marginLeft: 60,
  x: {
    grid: true,
    label: "Message Counts",
    type: "log",  // this causes all my data to disappear
    inset: 10
  },
  y: {
    type: "point",
    label: "Destinations"
  },
  marks: [
    Plot.dotX(data, Plot.groupY({x: "count"}, {y: "dest", sort: {y: "x", reverse: true}}))
  ]
})
1 Like