Is it possible to modify hover text for ggplotly after creating the plot?

36 Views Asked by At

Let's imagine I have data on three farms that have different assortments of fruits, veggies and berries they produce. I want to compare all of those between all of them and make a cool Venn diagram. However, I would also wish to incorporate the data on which types of produce are mutual for each two of them or for all the farms. The best thing would be making a plotly widget that would show how many groups are common instead of showing the text that apparently lists the data points used for placing the text (see the picture). Question: is it even possible to modify the ggplotly object post creation to achieve this behavior? Ideally I would like to see "Vegetables, Berries" (because those are the plant groups that are shared between B and C) in the dark gray box instead of whatever it's showing now.

The code:

library(ggvenn)
library(plotly)
# Fruits
fruits <- c("Apple", "Banana", "Orange", "Mango", "Pineapple", "Peach", "Pear", "Grapefruit", "Lemon", "Kiwi")

# Vegetables
vegetables <- c("Carrot", "Broccoli", "Cauliflower", "Spinach", "Kale", "Potato", "Onion", "Garlic", "Cucumber", "Tomato")

# Berries
berries <- c("Strawberry", "Blueberry", "Raspberry", "Blackberry", "Cranberry", "Gooseberry", "Elderberry", "Mulberry", "Boysenberry", "Currant")

fvb <- c(fruits, vegetables, berries)
set.seed(344)
vennda <- list("A" = sample(fvb, 10),
     "B" = sample(fvb, 10),
     "C" = sample(fvb, 10))

gg <- ggvenn(vennda)
ggp <- ggplotly(gg)
ggp

Picture of resulting plotly:

enter image description here

1

There are 1 best solutions below

0
Poiu Rewq On

Well, I found out that you can access hovertext labels pretty easily. The rest is just figuring out how to prepare those, so here's my answer for this, which seemingly worked

all_items <- c(fruits, vegetables, berries)
all_categories <- c(rep("Fruits", length(fruits)), rep("Vegetables", length(vegetables)), rep("Berries", length(berries)))
item_to_category <- setNames(all_categories, all_items)
#sub-function for generating correct intersections
find_unique_elements <- function(lst) {
  lapply(seq_along(lst), function(i) {
    current_set <- lst[[i]]
    other_sets <- do.call(c, lst[-i])
    setdiff(current_set, other_sets)
  })
}
# Function to calculate all intersections
calculate_intersections <- function(sets) {
  n <- length(sets)
  combs <- lapply(1:n, function(i) combn(1:n, i, simplify = FALSE))
  intersections <- lapply(combs, function(comb_set) {
    lapply(comb_set, function(indices) {
      Reduce(intersect, sets[indices])
    }) %>% find_unique_elements()
  })
  return(do.call(c, intersections))
}

# Function to generate hover texts
generate_hover_texts <- function(intersections, item_to_category) {
  lapply(intersections, function(intersect_set) {
    categories <- unique(item_to_category[intersect_set])
    paste(categories, collapse = ", ")
  })
}

# Calculate all intersections
all_intersections <- calculate_intersections(vennda)

# Generate hover texts
hover_texts <- generate_hover_texts(all_intersections, item_to_category)

# Hoverlabels are stored in ggp$x$data[[6]]$hovertext, so let's update hover texts in the Plotly object
ggp$x$data[[6]]$hovertext <- hover_texts
ggp

Ta-da