I have the following simple example of a clustered bar chart, by year:
library(highcharter)
year <- c(2017, 2018, 2019, 2020, 2021)
black <- c(12, 15, 23, 16, 11)
asian <- c(3, 12, 63, 46, 21)
white <- c(5, 45, 44, 44, 4)
hispanic <- c(23, 25, 44, 16, 112)
df <- data.frame(year, black, asian, white, hispanic)
highchart() %>%
hc_chart(type = "column") %>%
hc_xAxis(categories = df$year) %>%
hc_add_series(name="White",data = df$white) %>%
hc_add_series(name="Black",data = df$black) %>%
hc_add_series(name="Asian",data = df$asian) %>%
hc_add_series(name="Hispanic",data = df$hispanic)
Producing:
I want the years to be on top of the chart, and then each category labeled not by year, but by race, like this, more or less:
Same data as I have on the chart, just different formatting. I see no examples in highcharter that explain how to do this. Is it possible in highcharter?
I tweaked my code:
highchart() %>%
hc_chart(type = "column") %>%
hc_xAxis(opposite = TRUE, gridLineWidth = .3, categories = df$year) %>%
hc_add_series(name="White",data = df$white) %>%
hc_add_series(name="Black",data = df$black) %>%
hc_add_series(name="Asian",data = df$asian) %>%
hc_add_series(name="Hispanic",data = df$hispanic)
Which gives me:
How do I make the chart so that the series names (white/black/asian/hispanic) actually show up on the x-axis (repeating for each series, under the bars -- see above photo in original question) instead of just in a legend?
For moving the xAxis categories, use opposite: true
options. To enabled grid, set the xAxis.gridLineWidth
. Alternatively, you can use the Highcharts.SVGRenderer
to draw them. When it comes to the series name labels, my proposition is to use formatted dataLabels
and align them via chart.render
event.
Here is the JS config you can base on:
Highcharts.chart('container', {
chart: {
type: 'column',
marginBottom: 60,
events: {
render: function() {
var chart = this;
chart.series.forEach(function(s) {
s.points.forEach(function(p) {
if (p.dataLabel) {
p.dataLabel.attr({
y: chart.plotHeight + p.dataLabel.options.height / 2 + 5
});
}
});
});
}
}
},
xAxis: [{
lineWidth: 0.5,
opposite: true,
gridLineWidth: 1,
gridLineColor: 'grey',
categories: [
'2010',
'2015',
'2020',
]
}],
plotOptions: {
column: {
dataLabels: {
allowOverlap: true,
enabled: true,
rotation: -90,
formatter() {
return this.series.name
}
},
pointPadding: 0.2,
borderWidth: 0
}
},
legend: {
enabled: false
},
series: [{
name: 'Tokyo',
data: [49.9, 71.5, 106.4]
}, {
name: 'New York',
data: [83.6, 78.8, 98.5]
}, {
name: 'London',
data: [48.9, 38.8, 39.3]
}, {
name: 'Berlin',
data: [42.4, 33.2, 34.5]
}]
});
Demo: https://jsfiddle.net/BlackLabel/3y0ar58k/
API References: https://api.highcharts.com/highcharts/xAxis.opposite https://api.highcharts.com/highcharts/xAxis.gridLineWidth https://api.highcharts.com/highcharts/plotOptions.series.dataLabels.formatter https://api.highcharts.com/class-reference/Highcharts.SVGRenderer#path
EDIT:
The label's rendering
hc_chart(events = list(render= JS("function() { var chart = this; chart.series.forEach(function(s) { s.points.forEach(function(p) { if (p.dataLabel) { p.dataLabel.attr({ y: chart.plotHeight + p.dataLabel.options.height / 2 + 5 }); } }); }); } "))) %>%
hc_plotOptions(
column= list(
pointPadding: 0.2,
borderWidth: 0,
dataLabels = list(
allowOverlap: true,
enabled: true,
rotation: -90,
formatter = JS("function(){
return this.series.name
")
) )
)
) %>%