question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

using log() scale for bar chart y-axis

See original GitHub issue

Using 2.0.0-dev pulled on or about 1 Dec.

I’ve got a working chart with y-axis defined as

 .y(d3.scale.linear().domain([0, max_y_value]))

but the range of values are too diverse for the height of the graph. I changed to log scale:

 .y(d3.scale.log().domain([0, max_y_value]))

and the graph disappears - each bar is plotted with y=0 and height=0:

<rect class="bar" fill="#CFEAF3" x="92.96428571428571" y="0" width="47" height="0"></rect>

I presume this is since log(0) == -Infinity, so I convert the domain lower bound to 1:

.y(d3.scale.log().domain([1, max_y_value]))

that results in seemingly-accurate y-values but a height of Infinity:

<rect class="bar" fill="#CFEAF3" x="92.96428571428571" y="24.240901843984844" width="47" height="Infinity"></rect>

Infinity is from this block of code:

function barHeight(d) {
    return dc.utils.safeNumber(Math.abs(_chart.y()(d.y + d.y0) - _chart.y()(d.y0)));
}

_chart.y() is log() and d.y0 is always 0 - resulting in height="Infinity" for each bar.

I can’t find any docs on y0, nor any assignment in the source. Is it a bug? Do I have to set the domain/range elsewhere?

Thanks in advance.

Issue Analytics

  • State:open
  • Created 10 years ago
  • Comments:14 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
gordonwoodhullcommented, May 8, 2019

My attempt above did not deal with stacks potentially having empty values.

It only corrected the bottom stack. If the bottom stack is zero you also have to set the y0 of the next one, and so on.

It’s simplest just to change any y0 = 0 into y0 = 1

          var oldStack = chart.stackLayout();
          var newStack = function() {
              var stacked = oldStack.apply(oldStack, arguments);
              stacked.forEach(function(stack) {
                stack.values.forEach(function(v) {
                  if(v.y0 === 0) v.y0 = 1;
                });
              })
              return stacked;
          };
          newStack.values = function(v) {
              return arguments.length ? oldStack.values(v) : oldStack.values();
          };
          chart.stackLayout(newStack);

I don’t think it’s a bad solution at all. Of course it won’t work if any values are less than 1, but I haven’t seen anyone try to use log scales for fractional values so we can cross that bridge when we come to it.

I still need to port it to d3v4 and DCv3 and create an example.

I’ll keep this open until I create the example. This code has the potential to be added to the library, too.

The fiddle was also broken due to the upgrade to dc 3. Here’s a corrected fiddle, with a pie chart to test filtering:

https://jsfiddle.net/gordonwoodhull/eg392fvx/84/

0reactions
jpgricommented, Sep 27, 2019

Hi, I solve this issue in this simple way:

  1. Use linear scale and a Logarithmic function accesor

myBarChart.y(d3.scaleLinear().domain([min_value, max_value])) myBarChart.valueAccessor((d) => { return Math.log10(d.value) })

  1. Transform tick labels using the inverse function (i.e. exponential) myBarChart.yAxis().tickFormat(function (d) { return '' + 10 ** d; });
  2. Set appropriate tick labels to show in the graph (eventually could be util to use some round if your tick points have decimals) myBarChart.yAxis().tickValues([10, 100, 1000, 10000].map((e) => { return Math.log10(e); }));

In case yo have filters that make this bar chart to go 0 values, it could brake your chart and get sucked. In this case instead of use Math.log10(d) you could use ’ Math.log10(d+eps) and the inverse function 10 ** d - eps, where eps is any real positive value. Take care replacing this functions in the there point mentioned to have consistency between values and tick labels… It happens to me and I solved this way.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Advice: Bar graphs with log axes rarely make sense - GraphPad
A log scale has no logical starting place, so the choice is arbitrary. The graphs below show the same data as the graph...
Read more >
Setting both axes logarithmic in bar plot matploblib
I'd like to set both axes in the plot to a logarithmic scale. If I set plt. bar(x, y, width=10, color='b', log=True) which...
Read more >
Plot bar chart with log scale on y axis - MATLAB Answers
Hello there, I want to plot a group bar chart with differences about 10^-4 within the data, positiv and negativ. So the problem...
Read more >
How to put the y-axis in logarithmic scale with Matplotlib
The method yscale() takes a single value as a parameter which is the type of conversion of the scale, to convert y-axes to...
Read more >
using log scale in a bar chart - microsoft excel - Super User
As log 1 = 0, all numbers between 0 and 1 have negative logs, therefore your chart is shown "upside down". If you...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found