简体   繁体   中英

amcharts4 proper way to handle zero values on logarithmic value axis

I want to display some data with high variety in amcharts4, so I like to use the logarithmic scale on the value axis. Unfortunately the data contain some zero values, which of course can't be displayed with logarithmic scale.

I tried to change the zero values to 1 before rendering the chart, which would work, but now the values are not correct any more.

data.forEach(item => {
  for (const key in item) {
    if (item[key] === 0) {
      item[key] = 1;
    }
  }
});

Is there any better way to handle zero values with logarithmic value axis, that I can display the correct data?

Here is a code pen, which shows my current solution.

Edit

As of version 4.9.34, treatZeroAs is officially supported. Just set it on the value axis to the desired value to remap your zero values to:

valueAxis.treatZeroAs = 0.1;

Updated codepen .

The below workaround isn't needed anymore, but you may find the value axis adapter snippet helpful in changing the first label when using treatZeroAs .

Old method - pre 4.9.34

There doesn't appear to be a direct equivalent to v3's treatZeroAs property, which automatically handled this sort of thing. Pre-processing the data is one step, but you can also copy the original value into a separate object property and use a series tooltip adapter to dynamically show your actual value:

data.forEach(item => {
  for (const key in item) {
    if (item[key] <= 0) {
      item[key+"_actual"] = item[key]; //copy the original value into a different property
      item[key] = 1;
    }
  }
});
// ...

//display actual data that was re-mapped if it exists
chart.series.each((series) => {
  series.adapter.add("tooltipText", (text, target) => {
    if (target.dataFields) {
      let valueField = target.dataFields.valueY;
      let tooltipData = target.tooltipDataItem;
      if (tooltipData.dataContext[valueField + "_actual"] !== undefined) { 
        return '{' + valueField + '_actual}';
      }
      else {
        return text;
      }
    }
    else {
      return text;
    }
  })
});

If you want to fake a zero label, you can use an adapter for that as well since your smallest value in this case will be 1:

//fake the zero axis label
valueAxis.renderer.labels.template.adapter.add("text", (text) => {
  if (text === "1") {
    return "0"
  }
  else {
    return text;
  }
})

Codepen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM