I'm creating a shiny dashboard with a line chart using the Highcharter package in R to visualize export data over time for various countries. My goal is to have a unique color for each country, which remains consistent across both the chart lines and the legend. However, I'm running into a couple of issues.
Inconsistent Colors: The colors in the legend are assigned alphabetically, while the colors on the chart lines follow the order of selection, leading to mismatches. Attempted Solution with hc_colors: I tried using hc_colors() to set colors manually, but the chart lines and legend still don't align correctly.
Here's the code I'm using to generate the chart. The dataset is a simplified example, but it illustrates the same issue.
# Amostra de Dados
g_553 <- tribble(
~Ano, ~Nome_Pais, ~US_FOB, ~Peso_Liquido, ~Mean_Price,
"2011", "Alemanha", 0.00904, 16916796, 5.34e-10,
"2011", "Argentina", 0.0227, 15635607, 1.45e-9,
"2011", "Estados Unidos", 0.0258, 25018307, 1.03e-9,
"2011", "Países Baixos", 0.0124, 28620025, 4.34e-10,
"2012", "Alemanha", 0.00727, 13638592, 5.33e-10,
"2012", "Argentina", 0.0180, 12255622, 1.47e-9,
"2012", "Estados Unidos", 0.0266, 27089444, 9.83e-10,
"2012", "Países Baixos", 0.0134, 27368500, 4.89e-10,
"2013", "Alemanha", 0.00655, 14129010, 4.64e-10,
"2013", "Argentina", 0.0196, 13934551, 1.41e-9,
"2013", "Estados Unidos", 0.0224, 23668917, 9.45e-10,
"2013", "Países Baixos", 0.0133, 32895660, 4.06e-10,
"2014", "Alemanha", 0.00663, 13030649, 5.09e-10,
"2014", "Argentina", 0.0143, 15450241, 9.24e-10,
"2014", "Estados Unidos", 0.0270, 28510546, 9.47e-10,
"2014", "Países Baixos", 0.0110, 26537257, 4.14e-10,
"2015", "Alemanha", 0.00518, 9105968, 5.68e-10,
"2015", "Argentina", 0.0128, 11874210, 1.08e-9,
"2015", "Estados Unidos", 0.0240, 29218576, 8.22e-10,
"2015", "Países Baixos", 0.00782, 31780201, 2.46e-10,
"2016", "Alemanha", 0.00486, 6895825, 7.05e-10,
"2016", "Argentina", 0.0134, 10772268, 1.25e-9,
"2016", "Estados Unidos", 0.0231, 26001840, 8.90e-10,
"2016", "Países Baixos", 0.00695, 32095643, 2.17e-10,
"2017", "Alemanha", 0.00491, 6863967, 7.15e-10,
"2017", "Argentina", 0.0176, 11711823, 1.50e-9,
"2017", "Estados Unidos", 0.0269, 31227817, 8.60e-10,
"2017", "Países Baixos", 0.00742, 28361090, 2.62e-10,
"2018", "Alemanha", 0.00520, 6426912, 8.10e-10,
"2018", "Argentina", 0.0149, 11492885, 1.30e-9,
"2018", "Estados Unidos", 0.0287, 30565639, 9.38e-10,
"2018", "Países Baixos", 0.00823, 26976811, 3.05e-10,
"2019", "Alemanha", 0.00473, 5415819, 8.73e-10,
"2019", "Argentina", 0.00979, 7428020, 1.32e-9,
"2019", "Estados Unidos", 0.0297, 35390842, 8.39e-10,
"2019", "Países Baixos", 0.00716, 22950298, 3.12e-10,
"2020", "Alemanha", 0.00412, 4842317, 8.51e-10,
"2020", "Argentina", 0.00849, 6305341, 1.35e-9,
"2020", "Estados Unidos", 0.0215, 27669631, 7.75e-10,
"2020", "Países Baixos", 0.00670, 20548583, 3.26e-10
)
generate_country_analytics <- function(data, measure, country_filter) {
measure_column <- ifelse(measure == "value", "US_FOB", "Peso_Liquido")
# Filtrar e agrupar os dados
country_data <- data %>%
filter(Nome_Pais %in% country_filter) %>%
group_by(Ano, Nome_Pais) %>%
summarise(Measure = sum(!!as.symbol(measure_column), na.rm = TRUE), .groups = 'drop') %>%
ungroup() %>%
complete(Ano, Nome_Pais, fill = list(Measure = NA)) %>%
arrange(match(Nome_Pais, country_filter))
# Definir cores
colors <- RColorBrewer::brewer.pal(length(country_filter), "Dark2")[seq_along(country_filter)]
# Definir título e tooltip
title_measure <- ifelse(measure == "value", "Valor Exportado (US$)", "Peso Exportado (Toneladas)")
title_title <- paste0("Exportações por Ano e País - ", title_measure)
tooltip_text <- paste(
"<b>{point.Nome_Pais}</b><br>",
ifelse(
measure == "value",
"<b> Valor Exportado</b>: US$ {point.y:,.2f} mi",
"<b> Peso Exportado</b>: {point.y:,.2f} toneladas"
)
)
# Gráfico com Highcharts
highchart() %>%
hc_chart(zoomType = "x", backgroundColor = "#fff") %>%
hc_title(text = title_title) %>%
hc_xAxis(
title = list(text = "Ano"),
categories = unique(country_data$Ano),
gridLineColor = NULL,
lineColor = "#999999",
tickColor = "#999999"
) %>%
hc_yAxis(
title = list(text = title_measure),
gridLineColor = NULL,
lineColor = "#999999",
tickColor = "#999999"
) %>%
hc_add_series(
data = country_data,
type = "spline",
hcaes(x = Ano, y = Measure, group = Nome_Pais),
marker = list(enable = TRUE, symbol = "circle", radius = 3),
name = country_filter
) %>%
hc_colors(colors) %>%
hc_tooltip(useHTML = TRUE, pointFormat = tooltip_text) %>%
hc_legend(enabled = TRUE, align = 'center', layout = 'horizontal') %>%
hc_add_theme(hc_theme_smpl()) %>%
hc_exporting(enabled = TRUE)
}
filtered_data_country_analytics <- reactive({
req(input$value_country_analytics, input$country_country_analytics)
data_filtered <- g_553
if (!is.null(input$country_country_analytics)) {
data_filtered <- data_filtered %>%
filter(Nome_Pais %in% input$country_country_analytics)
}
return(data_filtered)
})
# renderização do gráfico
output$country_analytics <- renderHighchart({
data_filtered <- filtered_data_country_analytics()
generate_country_analytics(
data_filtered,
input$value_country_analytics,
input$country_country_analytics
)
})
# select the country
observe({
unique_countries <- unique(g_553$Nome_Pais)
updateSelectInput(
session,
inputId = "country_country_analytics",
choices = unique_countries,
selected = NULL
)
})
One option to fix your issue would be to convert Name_Pais
to a factor
with the levels
set according to country_filter
. Also, in that case you can drop the name=
parameter in hc_add_series
. The latter was the reason for the inconsistency as you did not account for the order of the series.
library(highcharter)
library(tidyverse)
generate_country_analytics <- function(data, measure, country_filter) {
measure_column <- ifelse(measure == "value", "US_FOB", "Peso_Liquido")
# Filtrar e agrupar os dados
country_data <- data %>%
filter(Nome_Pais %in% country_filter) %>%
group_by(Ano, Nome_Pais) %>%
summarise(Measure = sum(.data[[measure_column]], na.rm = TRUE), .groups = "drop") %>%
ungroup() %>%
complete(Ano, Nome_Pais, fill = list(Measure = NA)) %>%
mutate(Nome_Pais = factor(Nome_Pais, country_filter))
# Definir cores
colors <- RColorBrewer::brewer.pal(
length(country_filter), "Dark2"
)
# Definir título e tooltip
title_measure <- ifelse(measure == "value", "Valor Exportado (US$)", "Peso Exportado (Toneladas)")
title_title <- paste0("Exportações por Ano e País - ", title_measure)
tooltip_text <- paste(
"<b>{point.Nome_Pais}</b><br>",
ifelse(
measure == "value",
"<b> Valor Exportado</b>: US$ {point.y:,.2f} mi",
"<b> Peso Exportado</b>: {point.y:,.2f} toneladas"
)
)
# Gráfico com Highcharts
highchart() %>%
hc_chart(zoomType = "x", backgroundColor = "#fff") %>%
hc_title(text = title_title) %>%
hc_xAxis(
title = list(text = "Ano"),
categories = unique(country_data$Ano),
gridLineColor = NULL,
lineColor = "#999999",
tickColor = "#999999"
) %>%
hc_yAxis(
title = list(text = title_measure),
gridLineColor = NULL,
lineColor = "#999999",
tickColor = "#999999"
) %>%
hc_add_series(
data = country_data,
type = "spline",
hcaes(x = Ano, y = Measure, group = Nome_Pais),
marker = list(enable = TRUE, symbol = "circle", radius = 3)
) %>%
hc_colors(colors) %>%
hc_tooltip(useHTML = TRUE, pointFormat = tooltip_text) %>%
hc_legend(enabled = TRUE, align = "center", layout = "horizontal") %>%
hc_add_theme(hc_theme_smpl()) %>%
hc_exporting(enabled = TRUE)
}
generate_country_analytics(
g_553,
"value",
c("Alemanha", "Estados Unidos", "Argentina")
)