Plotly.js in relative barmode labels are overlapped when both bars have value 0

Viewed 362

Continue my journey with Plotly.js. I'm using relative barmode and need to show some customized text when both opposite bars have value 0. The issue that for value 0 both bars grow in the same direction and labels are overlapped: enter image description here

The only solution which I've thought about is checking when the value is 0 and change it dynamically to something like -0.009 and manually display the right value despite it's actually wrong. But it's cumbersome solution and chart keep rendering tiny bar for those values which isn't acceptable.

This is my example on Codepen

Can label direction be controlled manually? Thank you.

1 Answers

Initial Thoughts

One solution is to specify the base parameter for each trace as 0 and for the negative bars use a negative base value if the value is 0.

      const altbase=-1000/3;

      const trace1 = {
        x: xValue,
        y: [FN],
        name: `Model 1`,
        text: `${FN} <br> FN`,
        type: 'bar',
        base: 0,
        textposition: 'outside'
      };
      const trace2 = {
        x: xValue,
        y: [-TN],
        name: 'Model 1',
        text: `${TN} <br> TN`,
        base: altbase,
        type: 'bar',
        textposition: 'outside'
      };

It looks like -max_y_lim / 3 results in a good offset which is what altbase is used for.

You could also define altbase as a variable checking if TN==0:

var altbase = ((TN==0) ? -FP/3 : 0);

UPDATE1: or you can bypass the variable and put the if statement right into trace definition like base: ((TN==0) ? -FP/3 : 0),

UPDATE2: and a slightly more elegant equation for the offset would be:

var altbase = ((TN==0) ? -1.4/4*Math.max(FN,TN,TP,FP) : 0);

Final Update

After some thought it's probably best to always calculate altbase so that it's available to the other potential negative bar and then use an if statement for setting the base: where needed.

      var altbase = -1.4/4*Math.max(FN,TN,TP,FP);

      const trace1 = {
        x: xValue,
        y: [FN],
        name: `Model 1`,
        text: `${FN} <br> FN`,
        type: 'bar',
        base: 0,
        textposition: 'outside'
      };
      const trace2 = {
        x: xValue,
        y: [-TN],
        name: 'Model 1',
        text: `${TN} <br> TN`,
        base: ((TN==0) ? altbase : 0),
        type: 'bar',
        textposition: 'outside'
      };

Here is the implementation in CodePen.

enter image description here

Related