Set tooltip text for plot with more than one aes()

Viewed 228

In the ggplot below Im trying to change the hover text in points and columns using ggplotly() tooltip as text but I cannot change it. Also since I use 2 text for every aes() how does the tooltip know which one I pass to it?

library(ggplot2)
library(plotly)
dt2<-structure(list(year2 = c(1950, 1955, 1960, 1965, 1970, 1975, 
1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015), pta_count = c(2, 
4, 10, 14, 24, 18, 13, 19, 84, 100, 105, 96, 47, 15), scope_ntis_mean = c(3.5, 
9.5, 5, 9.57142857142857, 4.54166666666667, 11.7222222222222, 
6.23076923076923, 7.05263157894737, 17.1071428571429, 15.16, 
15.2761904761905, 17.6354166666667, 22.9574468085106, 26.8666666666667
), scope_ntis_sd = c(0.707106781186548, 11.7046999107196, 6.25388767976457, 
8.72409824049971, 4.56812364359683, 9.2278705436976, 5.11784209333462, 
10.7779284971676, 13.2864799994027, 12.9643801053175, 12.1295056958191, 
12.7964796077233, 12.4375963125981, 14.5791762782532), scope_ntis_se = c(0.822426813475736, 
9.62625905026287, 3.25294959458435, 3.83516264302846, 1.53376734188638, 
3.57760589505535, 2.33476117415722, 4.06710846230115, 2.38450123589789, 
2.13245076374089, 1.94704374916827, 2.14823678655809, 2.98410970181292, 
6.19176713030084), scope_ntis_cil = c(2.67757318652426, -0.12625905026287, 
1.74705040541565, 5.73626592840011, 3.00789932478029, 8.14461632716687, 
3.89600805661201, 2.98552311664622, 14.722641621245, 13.0275492362591, 
13.3291467270222, 15.4871798801086, 19.9733371066977, 20.6748995363658
), scope_ntis_ciu = c(4.32242681347574, 19.1262590502629, 8.25294959458435, 
13.406591214457, 6.07543400855305, 15.2998281172776, 8.56553040492645, 
11.1197400412485, 19.4916440930407, 17.2924507637409, 17.2232342253587, 
19.7836534532248, 25.9415565103236, 33.0584337969675)), row.names = c(NA, 
-14L), class = c("tbl_df", "tbl", "data.frame"))

p<-ggplot(dt2, aes(x=year2)) + 
      
      geom_col(aes(y=pta_count/(max(dt2$pta_count)/max(dt2$scope_ntis_ciu)),
                   text = paste(
                     "Year :",
                     ~year2,
                     "<br> Count of issues :",
                     ~pta_count/(max(dt2$pta_count)/max(dt2$scope_ntis_ciu))
                   )),
               fill="darkolivegreen",alpha=0.3,width=3)+
      geom_point(aes(y=scope_ntis_mean,
                     text = paste(
                       "Year :",
                       ~year2,
                       "<br> Count of issues :",
                       ~scope_ntis_mean
                     )))+
      geom_segment(aes(x=year2,y=scope_ntis_cil,xend=year2,yend=scope_ntis_ciu
                       ),
                   arrow=arrow(length=unit(0.1,"cm"),
                               ends='both'),
                   lineend="square",size=0.3) +
      scale_x_continuous(n.breaks=14)+
      # Custom the Y scales:
      scale_y_continuous(
        
        # Features of the first axis
        name = "NTI Scope\n(scope measures the sum of all NTIs mentioned in a PTA,\ndot indicated mean scope per 5-year interval,\n arrows signal confidence intervals)",
        
        # Add a second axis and specify its features
        sec.axis = sec_axis( ~ . * max(dt2$pta_count)/max(dt2$scope_ntis_ciu), name="PTA Count\n(green columns indicate number of PTAs\n signed in given 5-year intervall)")
      )+
      labs(x='')+
      theme_bw()+theme(axis.title = element_text(size = 8),
                       axis.title.y = element_text(margin = margin(t = 0, r = 20, b = 0, l = 0)))
    
    ggplotly(p,tooltip = "text")
1 Answers

Because you sent me the comment on your last question I looked at this from both perspectives. I kept getting errors with this code. Instead of focusing on resolving those issues, I'm going to show you how to customize the tooltips without first having created a ggplotly object and when you have already (like in your last question).

  1. Starting from a ggplot object
  2. Starting from a ggplotly or plotly object

1)

Since you are simply modifying tooltips that still represent the x- and y-axes, I think this is the easiest approach. I used stringr from within tidyverse to modify the tooltips.

library(tidyverse) 

# create plotly object to modify
p2 <- plotly_build(p)

# now modify the text calls for each trace that this applies to

# modfiy existing tooltips
# this is the first trace (the bar chart or first geom in ggplot object)
p2$x$data[[1]]$text <- str_replace_all(p2$x$data[[1]]$text, 
                                       "year2", "Year ") %>% 
  str_replace_all(., fixed("pta_count/(max(pta_count)/max(scope_ntis_ciu))"),
                  "Count of issues ")

# validate change
p2$x$data[[1]]$text # looks right

# now for the second trace
p2$x$data[[2]]$text <- str_replace_all(
  p2$x$data[[2]]$text, "year2", "Year ") %>% 
  str_replace_all(., "scope_ntis_mean", "Count of issues ")

# validate change
p2$x$data[[2]]$text # looks right

2)

First I added hoverinfo = "skip" to the invisible trace. Then I assigned the build of that ggplotly object to an object name. Please keep in mind this is using the version of the object p from your previous question.

p2 <- ggplotly(p) %>% 
  add_trace(inherit = F, x = ~year2,
            y = ~(pta_count/(max(pta_count)/ max(scope_ntis_ciu))
            ) * (max(dt2$pta_count)/max(dt2$scope_ntis_ciu)),
            data = dt2, 
            yaxis = "y2", 
            hoverinfo = "skip",               # NO TOOLTIPS!
            alpha = 0,                        # make it invisible
            type = "bar") %>% 
  layout(margin = list(l = 85, r = 85),
         yaxis2 = list(
           ticklen = 3.7,                     # to match other axes
           tickcolor = "rgba(51, 51, 51, 1)", # to match other axes
           tickfont = list(size = 11.7,       # to match other axes
                           color = "rgba(77, 77, 77, 1)"), # to match the others
           titlefont = list(size = 11.7),     # to match other axes
           side = "right",
           overlaying = "y",
           showgrid = F,      # to match ggplot version
           dtick = 25,        # between ticks
           title = "PTA Count\n(green columns indicate number of PTAs\n signed in given 5-year interval)"))


p2$x$data[[1]]$text <- str_replace_all(
  p2$x$data[[1]]$text, "year2", "Year ") %>% 
  str_replace_all(., fixed("pta_count/(max(pta_count)/max(scope_ntis_ciu))"),
                  "Count of issues ")
# validate
p2$x$data[[1]]$text

# now for the second trace
p2$x$data[[2]]$text <- str_replace_all(
  p2$x$data[[2]]$text, "year2", "Year ") %>% 
  str_replace_all(., "scope_ntis_mean", "Count of issues ")
# validate
p2$x$data[[2]]$text

Essentially, plotly_build and ggplotly create the same object. In both 1 and 2, p2 is ready to be called.

Related