When it comes to building interactive visualizations in R, the plotly package is one of my go-to’s. The ggplotly() function in this package allows me to create a visual in ggplot, wrap it, and presto - interactive visualization! While taking this approach on a recent project, I ran into an issue with my subtitle disappearing. Trial and error led me to a solution I wanted to share.

Create a ggplot

Below is the code to generate a scatterplot showing the population and life expectancy in all 50 states using data from base R. The data frame containing the pertinent state data is generated first. A scatterplot is then created using ggplot, specifying the color and size of the points, applying a minimal theme, formatting the axis labels (using the scales package), and finally specifying the various text labels to be added.

# Create data frame
df <- data.frame(State =,
                 LifeExp = state.x77[,4],
                 Population = state.x77[,1],
                 stringsAsFactors = F) %>%

# Create ggplot
p <- ggplot(df, aes(x = LifeExp, y = Population, label = State)) +
  geom_point(color = 'tomato', size = 2.5) +
  theme_minimal() +
  scale_x_continuous(labels = scales::comma) +
  scale_y_continuous(labels = scales::comma) +
  labs(x = 'Life Expectancy (years)',
       y = 'Population (thousands)',
       title = 'US State Population and Life Expectancy',
       subtitle = 'Life expectancy 1969-1971; Population estimate as of July 1, 1975')


At this point we have a nice looking visual!

Make it Interactive

While our static visual is nice, the audience can’t tell which state belongs to each point. Adding a tooltip when users hover over each point would fix this problem. The easist way to do this is with the ggplotly() function from the plotly package. Once the package is loaded, we simply wrap our ggplot object with this function.


Mission accomplished! Users can now hover over the various points and see specific information on life expectancy, population, and state. However, by wrapping our ggplot object in the ggplotly() function, notice that the subtitle disappeared. Our subtitle carried pertinent information for the user, so this is something we need to fix.

The Fix

Fixing the subtitle issue requires us to add the title and subtitle via another plotly function called layout(). Within this function, we can specify a title that will supersede the ggplot title.

Since the layout() function only has a title (and not subtitle) argument, we have to use some HTML to format our text to get it just right. Only certain HTML tags are allowed in this argument, but the ones we need are available (see this reference from plotly for more information). By using a combination of a line break (br) and superscript (sup), we can create the title and subtitle for our plot.

ggplotly(p) %>%
  layout(title = list(text = paste0('US State Population and Life Expectancy',
                                    'Life expectancy 1969-1971; Population estimate as of July 1, 1975',

There we have it. An interactive visualization for others to explore that looks exactly like our original ggplot.

NOTE: This tutorial requires the latest version of the plotly package, version 4.9.0