I have been trying to add a second y-axis (showing percentages) to my highcharter plot, however I cannot get it right.
Using dummy data such as this one:
# Sample data
set.seed(1234)
df <- data.frame(
Name = LETTERS[1:5],
Type = paste0("Type ", c(1, 1, 2, 2, 1)),
Value = rnorm(5, 150, 10)
)
df$Percentage = df$Value / sum(df$Value)
I can achieve what I'm trying to do using ggplot like this:
# ggplot with 2 axis
library(ggplot2)
ggplot(df, aes(x=Type, y=Value, fill=Name)) +
geom_col(position="stack") +
scale_y_continuous(sec.axis = sec_axis(~ . / sum(df$Value), labels = scales::label_percent())) +
theme_light()
But in highcharter, the second y-axis is only visible if I add another series to my plot, such as shown here:
library(highcharter)
highchart2() |>
hc_plotOptions(
column = list(
borderWidth = 0,
stacking = "normal",
tooltip = list(valueDecimals = 2)
)
) |>
hc_add_series(data = df, hcaes(x = Type, y = Value, group = Name), type = "column") |>
hc_add_series(data = df, hcaes(x = Type, y = Percentage, group = Name), type = "column", yAxis = 1) |>
hc_xAxis(type="category") |>
hc_yAxis_multiples(
list(lineWidth = 0, title = list(text="Amount")),
list(showLastLabel = FALSE, opposite = TRUE, title = list(text="Percentage"))
)
However, when turning the second series invisible, using the visible=F
argument, the tick values of my second y-axis disappear and all I have left is its title.
Is it possible to do what I am trying to do using highcharter?
Instead of setting the visible option to false I suggest changing color to transparent, disabling tooltip and removing the series from the legend. Then the axis is displayed correctly even though there are no actual points on the chart.
Here's how it looks like in js: https://jsfiddle.net/BlackLabel/70qa9snz
// Sample data
const data = [
{ name: "A", type: "Type 1", value: 160 },
{ name: "B", type: "Type 1", value: 140 },
{ name: "C", type: "Type 2", value: 150 },
{ name: "D", type: "Type 2", value: 155 },
{ name: "E", type: "Type 1", value: 145 },
]
const totalValue = data.reduce((sum, item) => sum + item.value, 0)
const seriesData = data.map((item) => ({
name: item.name,
y: item.value,
percentage: item.value / totalValue,
}))
Highcharts.chart("container", {
chart: {
type: "column",
},
title: {
text: "Chart with Secondary Y-Axis",
},
xAxis: {
categories: [...new Set(data.map((item) => item.type))],
crosshair: true,
},
yAxis: [
{
title: {
text: "Amount",
},
},
{
title: {
text: "Percentage",
},
opposite: true,
labels: {
format: "{value:.2%}",
},
},
],
plotOptions: {
column: {
stacking: "normal",
},
},
series: [
{
name: "Values",
data: seriesData.map((item) => item.y),
},
{
name: "Percentage",
data: seriesData.map((item) => item.percentage),
yAxis: 1,
color: "transparent",
showInLegend: false,
enableMouseTracking: false,
},
],
})