0

I used ggplot2 and ggplotly to compose a density chart of a given variable (population per census tract, in two groups). The tooltip shows six decimal places for the variable:

persons_per_census_tract: 16.684932

However, I want it to show integers:

persons_per_census_tract: 17

the plot as it looks now

Code:

### create dummy data
# normal distribution
rnorm1 <- rnorm(200, mean=10, sd=3)

# dataframe with the urban/rural labels and normal distribution
data <- data.frame(spatial_type = rep(c("1: urban", "2: rural"), each = 200 / 2),
                   persons_per_census_tract = rnorm1)


# define a function to combine several histograms in one plot, inspired by 
# https://stackoverflow.com/a/53680101
# here already defining some parts of the appearance (y axis, outline size, colour via scale_fill_manual)
plot_multi_histogram <- function(df, feature, label_column) {
  plt <- ggplot(df, aes(x=!!sym(feature),
                        fill=!!sym(label_column)),
                text=paste(scales::percent(!!sym(feature)), "persons/census tract")) +
    scale_fill_manual(
      values=c("#9BB7B0", "#2DC6D6"),
      breaks=c("1: urban", "2: rural")) +   
    geom_density(alpha=.7, size = .2) +
    scale_y_continuous(labels = scales::unit_format(scale = 100, unit = "%")) +  
    labs(x=feature, y="density")
  plt <- plt + guides(fill=guide_legend(title=label_column))
  
  # Convert ggplot to a plotly object
  plt <- ggplotly(plt, tooltip=c(feature))
  
  return(plt)
}


# revert factor order of spatial_type to determine rendering order
# https://stackoverflow.com/a/43784645
data$spatial_type <- factor(data$spatial_type, c("2: rural", "1: urban"))

# Apply the function to create the plot based on dummy data
density.p <- plot_multi_histogram(data, 'persons_per_census_tract', 'spatial_type')

# print the plot
plotly::ggplotly(density.p)

I've tried to include several options into the code that defines the function plot_multi_histogram <- ...

, e.g. scales::percent

text=paste(scales::percent(!!sym(feature)), "persons/census tract")

or as.integer

text=paste(as.integer(!!sym(feature)), "persons/census tract")

or sprintf() or round().

I suppose the rounding attempts fail because they are embedded in the function. Any ideas? Thx!

  • 1
    Does this answer your question? [How to round the hover information when using ggplotly?](https://stackoverflow.com/questions/56066622/how-to-round-the-hover-information-when-using-ggplotly) – mhovd Aug 18 '23 at 08:50
  • Nope. :( `round()` does not work, regardless of the position, i.e., neither of `!!sym(round(feature))` or `round(!!sym(feature))` delivers a rounded tooltip. – fluegelrad Aug 18 '23 at 08:55

1 Answers1

1

First issue is that you have set tooltip=feature. Hence, the value for the tooltip is taken from the raw feature column of your dataset. That's the reason why changing anything in text=... has no effect. Second, you have put text= outside of aes() in ggplot(). Well, in case of ggplot() all arguments outside of aes() will be silently ignored. If you want create a tooltip from a data column using !!sym() you have to do that inside aes().

Unfortunately simply moving text= inside aes() will also not fix the issue as this works only fine in case of geoms using stat="identity". Perhaps there is a more straightforward approach I'm not aware of. But one fix would be to set and format the tooltip text using after_stat and of course by setting tooltip="text" in ggplotly:

library(ggplot2)
library(plotly)

set.seed(123)

plot_multi_histogram <- function(df, feature, label_column) {
  plt <- ggplot(df, aes(
    x = !!sym(feature),
    fill = !!sym(label_column)
  )) +
    scale_fill_manual(
      values = c("#9BB7B0", "#2DC6D6"),
      breaks = c("1: urban", "2: rural")
    ) +
    geom_density(
      aes(text = after_stat(
        paste(
          scales::number(x, accuracy = 1), "persons/census tract"
        )
      )),
      alpha = .7, size = .2
    ) +
    scale_y_continuous(labels = scales::unit_format(scale = 100, unit = "%")) +
    labs(x = feature, y = "density")
  plt <- plt + guides(fill = guide_legend(title = label_column))

  ggplotly(plt, tooltip = "text")
}

data$spatial_type <- factor(data$spatial_type, c("2: rural", "1: urban"))

plot_multi_histogram(data, "persons_per_census_tract", "spatial_type")

enter image description here

stefan
  • 90,330
  • 6
  • 25
  • 51
  • 1
    Works neatly. Thanks a lot! – fluegelrad Aug 18 '23 at 10:06
  • Can you tell me how to add a `y` value as well? When directly entering it similar to the `x`, I get the response "object 'y' not found". I succeeded to add the correct density value for each row to my dataframe, but I don't know how to fetch it from there. Nesting the `y` in `aes()` of `ggplot()` blows up my density plot. :/ – fluegelrad Aug 18 '23 at 21:44
  • No need to add a colum with the density value. Inside after_stat you can get the density value using `density`. See also this answer by me for some explanation: https://stackoverflow.com/questions/75988042/customizing-tooltip-using-ggplotly-and-geom-density/75988554#75988554 – stefan Aug 19 '23 at 05:53