Hiding Small Pie Slices

Pie chart sizes its slices proportionally, based on the relative values. Sometimes that means that we end up with a chart that has a bunch of small-value slices that are barely visible, but clutter up the chart.

Here's one chart like that:

See the Pen amCharts 4: hide labels for small slices by amCharts team (@amcharts) on CodePen.0

Ewww. Let's see what we can do about it.

Hiding labels

Let's hide labels (and ticks) of the slices that are less than X percent of the whole slice.

We can hide or show any element in amCharts 4 using their hide() or show() methods respectively.

We also have a bunch of events at our disposal we can use to toggle element visibility.

Let's build some to auto-hide labels and ticks.

pieSeries.ticks.template.events.on("ready", hideSmall);
pieSeries.ticks.template.events.on("visibilitychanged", hideSmall);
pieSeries.labels.template.events.on("ready", hideSmall);
pieSeries.labels.template.events.on("visibilitychanged", hideSmall);

function hideSmall(ev) {
  if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
    ev.target.hide();
  }
  else {
    ev.target.show();
  }
}
pieSeries.ticks.template.events.on("ready", hideSmall);
pieSeries.ticks.template.events.on("visibilitychanged", hideSmall);
pieSeries.labels.template.events.on("ready", hideSmall);
pieSeries.labels.template.events.on("visibilitychanged", hideSmall);

function hideSmall(ev) {
  if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
    ev.target.hide();
  }
  else {
    ev.target.show();
  }
}
{
  // ...
  "series": [{
    // ...
    "ticks": {
      "events": {
        "ready": function(ev) {
          if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
            ev.target.hide();
          }
          else {
            ev.target.show();
          }
        },
        "visibilitychanged": function(ev) {
          if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
            ev.target.hide();
          }
          else {
            ev.target.show();
          }
        }
      }
    },
    "labels": {
      "events": {
        "ready": function(ev) {
          if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
            ev.target.hide();
          }
          else {
            ev.target.show();
          }
        },
        "visibilitychanged": function(ev) {
          if (ev.target.dataItem && (ev.target.dataItem.values.value.percent < 5)) {
            ev.target.hide();
          }
          else {
            ev.target.show();
          }
        }
      }
    },
  }]
}

Let's check how we're doing now.

See the Pen amCharts 4: hide labels for small slices by amCharts team (@amcharts) on CodePen.0

Better. Now small irrelevant slices do not clutter up the interface, but still identifiable via hover or legend.

Hiding slices

But what about we don't want to show those small slices at all?

We could use the same hidden adapter for slices template as well:

pieSeries.slices.template.adapter.add("hidden", hideSmall);
pieSeries.slices.template.adapter.add("hidden", hideSmall);
{
// ...
"series": [{
// ...
"slices": {
"adapter": {
"hidden": function hideSmall(hidden, target) {
return target.dataItem.values.value.percent < 5 ? true : false;
}
}
}
}]
}

However, they would just be hidden, without the rest of the slices moving in to claim the freed up space.

See the Pen amCharts 4: hide labels for small slices by amCharts team (@amcharts) on CodePen.0

While not faulty per se empty space indicates that we have removed something.

But what about if we want to completely eliminate hidden slices?

In this case simple adapter won't do.

Removing slices

For this to work, we will need to hide not just respective visual element of the slice, but whole "data item".

In this case, Pie series will re-adjust itself so that remaining slices take up all of the pie.

For that we will utilize Pie series event datavalidated which happens right after data is being supplied to the series, because we will need it in order to check which slices to hide.

And, while we're at it, we will also hide related legend items.

pieSeries.events.on("datavalidated", function(ev) {
ev.target.slices.each(function(slice) {
if (slice.dataItem.values.value.percent < 5) {
slice.dataItem.hide();
slice.dataItem.legendDataItem.hide();
}
});
});
pieSeries.events.on("datavalidated", function(ev) {
ev.target.slices.each(function(slice) {
if (slice.dataItem.values.value.percent < 5) {
slice.dataItem.hide();
slice.dataItem.legendDataItem.hide();
}
});
});
{
// ...
"series": [{
// ...
"events": {
"datavalidated": function(ev) {
ev.target.slices.each(function(slice) {
if (slice.dataItem.values.value.percent < 5) {
slice.dataItem.hide();
slice.dataItem.legendDataItem.hide();
}
});
}
}
}]
}

See the Pen amCharts 4: hide labels for small slices by amCharts team (@amcharts) on CodePen.0

Grouping small slices

If you would rather not hide labels or slices themselves, you can use Slice Grouper plugin do dynamically group small slices into one "Other" slice.