Error Chart
A line chart with error bars: each country’s value comes with a bar showing how far off it could be. Where two bars overlap, the two values could be the same.
About this chart
When to show error bars
Every estimate has some uncertainty: a survey’s margin of error, the spread of repeated tests. Error bars put it on the chart, so readers don’t see meaning in differences smaller than the margin.
Good for
- Survey results with a margin of error
- Lab or test results averaged over several runs
- Estimates or forecasts side by side
Think twice when
- Categories with no order, like countries: drop the connecting line
- Readers who don’t know what the bars mean: say it in a note
- Errors bigger on one side: draw low and high ends separately, or use a range area
For developers
Get the code.
Built with amCharts 5, a JavaScript library. The code includes your theme and renderer (canvas or SVG), but not the changes you make with the controls.
For projects that use npm:
How it reads:
npm install @amcharts/amcharts5. See Getting started.
The same chart as a JSON config. Chart Maker reads and writes this format, the library's JSON parser turns it into a chart, and the <am5-chart> element puts it on a page with no code.How it reads:
"type" is the class to create and "settings" what you would pass to its new() in code; "properties" fill in its parts, lists such as series and axes or templates such as columns.template; "refs" holds objects used in more than one place ("#series-0" stands for the one named series-0); a string starting with "@" takes a value from another object, such as "@series.get('fill')".
A complete page. Save it as an .html file and open it in a browser.
Paste this into an AI coding assistant to build the chart from scratch. More in amCharts & AI.
var data = [
{
country: "USA",
visits: 3025,
error: 100
},
{
country: "China",
visits: 1882,
error: 180
},
{
country: "Japan",
visits: 1809,
error: 130
},
{
country: "Germany",
visits: 1322,
error: 200
},
{
country: "UK",
visits: 1122,
error: 150
},
{
country: "France",
visits: 1114,
error: 110
},
{
country: "India",
visits: 984,
error: 120
}
];
// Create root element
// https://docs.amcharts.com/v5/getting-started/#root-element
var root = am5.Root.new("chartdiv");
// Set themes
// https://docs.amcharts.com/v5/concepts/themes/
root.setThemes([
am5themes_Animated.new(root),
am5themes_Responsive.new(root)
]);
// Create chart
// https://docs.amcharts.com/v5/charts/xy-chart/
var chart = root.container.children.push(
am5xy.XYChart.new(root, {
panX: true, // drag the plot to pan...
panY: true, // ...in any direction
wheelY: "zoomXY", // the wheel zooms both ways
pinchZoomX: true // pinch with two fingers to zoom on touch screens
})
);
chart.get("colors").set("step", 2);
// Add scrollbar, hidden at first
// https://docs.amcharts.com/v5/charts/xy-chart/scrollbars/
chart.set("scrollbarX", am5.Scrollbar.new(root, { orientation: "horizontal", forceHidden: true }));
// Create axes
// https://docs.amcharts.com/v5/charts/xy-chart/axes/
var xRenderer = am5xy.AxisRendererX.new(root, {
minGridDistance: 50 // at least 50px between labels; on narrow screens some are skipped
});
var xAxis = chart.xAxes.push(
am5xy.CategoryAxis.new(root, {
categoryField: "country",
renderer: xRenderer,
tooltip: am5.Tooltip.new(root, {}) // shows the hovered country on the axis
})
);
// grid lines at the end of each category's cell instead of at its start
xRenderer.grid.template.setAll({
location: 1
})
var yAxis = chart.yAxes.push(
am5xy.ValueAxis.new(root, {
// 10% room above and below the values, so the error bars at either end fit
extraMax: 0.1,
extraMin: 0.1,
renderer: am5xy.AxisRendererY.new(root, {
strokeOpacity: 0.1 // a faint line along the value axis
}),
tooltip: am5.Tooltip.new(root, {}) // shows the value at the cursor's height
})
);
// Create series
// https://docs.amcharts.com/v5/charts/xy-chart/series/
var series = chart.series.push(
am5xy.LineSeries.new(root, {
calculateAggregates: true, // computes totals, averages and the like, for use in labels
xAxis: xAxis,
yAxis: yAxis,
valueYField: "visits",
categoryXField: "country",
tooltip: am5.Tooltip.new(root, {
labelText: "{categoryX}: {valueY} ± {error}" // as "USA: 3025 ± 100"
})
})
);
// add error bullet: a vertical bar from value - error to value + error,
// with a cap at each end
series.bullets.push(function() {
var graphics = am5.Graphics.new(root, {
strokeWidth: 2, // 2px lines...
stroke: series.get("stroke"), // ...in the series' color
draw: function(display, target) { // a custom draw function: the bar and its two caps
var dataItem = target.dataItem;
var error = dataItem.dataContext.error;
// the error in pixels, at the current zoom
var yPosition0 = yAxis.valueToPosition(0);
var yPosition1 = yAxis.valueToPosition(error);
var height =
yAxis.get("renderer").positionToCoordinate(yPosition1) - yAxis.get("renderer").positionToCoordinate(yPosition0);
display.moveTo(0, -height); // the bar, reaching the error above and below the point
display.lineTo(0, height);
display.moveTo(-10, -height); // a 20px cap at one end...
display.lineTo(10, -height);
display.moveTo(-10, height); // ...and one at the other
display.lineTo(10, height);
}
});
return am5.Bullet.new(root, {
// redrawn whenever the series changes, so the bar's height follows the zoom
dynamic: true,
sprite: graphics
});
});
// Add circle bullet
// https://docs.amcharts.com/v5/charts/xy-chart/series/#bullets
series.bullets.push(function() {
var graphics = am5.Circle.new(root, {
strokeWidth: 2, // a 2px outline
radius: 5, // 5px radius
stroke: series.get("stroke"), // in the line's color
fill: root.interfaceColors.get("background") // filled with the background color
});
return am5.Bullet.new(root, {
sprite: graphics
});
});
// Add cursor
// https://docs.amcharts.com/v5/charts/xy-chart/cursor/
chart.set("cursor", am5xy.XYCursor.new(root, {
xAxis: xAxis,
yAxis: yAxis,
snapToSeries: [series] // the cursor jumps to the nearest point of the series
}));
series.data.setAll(data);
xAxis.data.setAll(data);
// Make stuff animate on load
// https://docs.amcharts.com/v5/concepts/animations/
series.appear(1000);
chart.appear(1000, 100);



