1
votes

I've written a function to pull data into a highcharter cloropleth map. I'm having a very difficult time trying to figure out how to format the values going into the map based on whether they are counts (needing format with commas and no decimal places) or percents(needing to be multiplied by 100 and a % sign added as prefix)

The function takes in a dataframe x and selects the variable corresponding to the label assigned to the desired variable which is provided as y. In this reprex you can change out "Count" for "Percent" to change the map. In my actual dashboard, the map changes dynamically based on which variable label is selected through a dropdown input selector using flexdashboard.

I think that the solution should be to create an if statement within the hc_tooltip() to apply a comma format with no decimals if the value is > 1 or multiply the value by 100 and add a % prefix if value < 1.

I've tried reading highcharter documentation to attempt to figure this out but I really have zero formal programming training and don't know any javascript so the highcharter documentation is very hard for me to understand. It seems like one way it could be done is to use a JS function within hc_tooltip(), something like hc_tooltip(formatter = JS("function() {}). I can't figure out how to reference the values of {point.value} within a function like that. I've found a few stackoverflow posts that seem to be similar to my problem but I don't understand how to modify my code to make them work. One post I've been trying to understand is this one: Tooltip content within a highchart in Rshiny

I've tried using scales::percent() and scales::comma() on the appropriate values in the dataframe before they are passed to the map (like right after creating df) but it seems like hc_add_series_map() doesn't like it when the variables are passed in that way.

Please help me understand how to solve this or provide a solution that I can use to understand. In my short time learning to code in R I think this might be the thing I've struggled with the longest and I'm feeling pretty dispirited right now that I can't figure this out.

library(tidyverse) 
library(utils) 
library(stats) 
library(labelled)
library(highcharter)
library(shiny) 
library(expss)

x<- structure(list(state = structure(c("Alabama", "Alaska", "Arizona", 
                                       "Arkansas", "California", "Colorado", "Connecticut", "Delaware", 
                                       "District Of Columbia", "Florida", "Georgia", "Hawaii", "Idaho", 
                                       "Illinois", "Indiana", "Iowa", "Kansas", "Kentucky", "Louisiana", 
                                       "Maine", "Maryland", "Massachusetts", "Michigan", "Minnesota", 
                                       "Mississippi", "Missouri", "Montana", "Nebraska", "Nevada", "New Hampshire", 
                                       "New Jersey", "New Mexico", "New York", "North Carolina", "North Dakota", 
                                       "Ohio", "Oklahoma", "Oregon", "Pennsylvania", "Rhode Island", 
                                       "South Carolina", "South Dakota", "Tennessee", "Texas", "Utah", 
                                       "Vermont", "Virginia", "Washington", "West Virginia", "Wisconsin", 
                                       "Wyoming"), label = "State"), count = structure(c(88972, 18217, 
                                                                                         99224, 43942, 451964, 79864, 74454, 20558, 24895, 327488, 140264, 
                                                                                         28621, 26095, 204099, 127416, 59616, 60374, 72304, 62918, 27603, 
                                                                                         86983, 147895, 149864, 116927, 48100, 119469, 18994, 32954, 48781, 
                                                                                         24601, 137461, 29405, 382436, 143585, 15428, 229085, 49448, 68338, 
                                                                                         229429, 25817, 72222, 18926, 107276, 350382, 36801, 20696, 109693, 
                                                                                         108594, 34110, 105354, 8107), label = "Count"), pctState = structure(c(0.0174, 
                                                                                                                                                                0.0036, 0.0194, 0.0086, 0.0883, 0.0156, 0.0146, 0.004, 0.0049, 
                                                                                                                                                                0.064, 0.0274, 0.0056, 0.0051, 0.0399, 0.0249, 0.0117, 0.0118, 
                                                                                                                                                                0.0141, 0.0123, 0.0054, 0.017, 0.0289, 0.0293, 0.0229, 0.0094, 
                                                                                                                                                                0.0234, 0.0037, 0.0064, 0.0095, 0.0048, 0.0269, 0.0057, 0.0748, 
                                                                                                                                                                0.0281, 0.003, 0.0448, 0.0097, 0.0134, 0.0448, 0.005, 0.0141, 
                                                                                                                                                                0.0037, 0.021, 0.0685, 0.0072, 0.004, 0.0214, 0.0212, 0.0067, 
                                                                                                                                                                0.0206, 0.0016), label = "Percent")), row.names = c(NA, -51L), class = "data.frame")

y<- "Count". #change y to "Percent" to get the other value in the dataframe for display

get_map <- function(x, y){
  data("usgeojson")
 
  z<- look_for(x, y, details= FALSE, labels = TRUE,
               ignore.case = FALSE)
  a<- z$variable
  
  df<- x %>%
    select(all_of(a))
  
  metric1<- y
  value1<-  colnames(df)
 
  highchart() %>%
    hc_add_series_map(usgeojson, x,
                      name = metric1,
                      value = value1,
                      joinBy = c("woename", "state"))%>%
    hc_mapNavigation(enabled = T) %>%
    hc_tooltip(pointFormat = "{point.value}"
               ) %>%
    hc_colorAxis(min= min(df),
                 max= max(df),
                 startOnTick= FALSE,
                 endOnTick= FALSE)
}

get_map(x, y)

1
Please use jsfiddle for create a minimal reproducible example of your chart with sample data.Marco Aurelio Fernandez Reyes
This is an Rstudio IDE reprex that includes sample data. It should run perfectly in Rstudio. I I've never used jsfiddleClark
Clark, thanks for your comment. I don't know how to use Rstudio - not familiar with it and I've mentioned jsfiddle due you tagged your question with javascript, hence, I though the code you shared could be run on jsfiddle. Good luck.Marco Aurelio Fernandez Reyes

1 Answers

0
votes

I finally figured this out! It took a lot of time this last week but it works now. The solution has two parts. One part was to add formatting instructions for highcharter to my dashboard before entering the function to format values with a thousands separator

lang<-getOption("highcharter.lang")
lang$thousandsSep<-","
options(highcharter.lang = lang)

The second part was to re-write my function with some ifelse statements to separate the dataframe into the variables that needed to be formatted by percent and those that didn't.

get_map <- function(x, y){
  data("usgeojson")
  
  z<- look_for(x, y, details= FALSE, labels = TRUE,
               ignore.case = FALSE)
  a<- z$variable
  
  df<- x %>%
    select(all_of(a))
  
  decimals<-ifelse(mean(df[,1])>1,0,1)
  
  df[1]<-ifelse(mean(df[,1])>1,df[1],df[1]*100)    
  df[2]<-x[1]
  
  value1<-  colnames(df[1])
  highchart() %>%
    hc_add_series_map(usgeojson, df,
                      name = y,
                      value = value1,
                      joinBy = c("woename", "state"))%>%
    hc_mapNavigation(enabled = T) %>%
    hc_tooltip(valueDecimals= decimals,valueSuffix=ifelse(mean(df[,1])>100 | value1== "popratio","","%")
    ) %>% 
    hc_colorAxis(min= min(df[1]),
                 max= max(df[1]),
                 startOnTick= FALSE,
                 endOnTick= FALSE)
}

Ultimately it didn't actually require any JS function, although I imagine it still could have been solved that way as well. It was difficult to figure out the highcharter settings and convert them into syntax that worked with R.