Search code examples
rggplot2plotly

ggplotly: unable to add a frame in PCA score plot in ggplot2


I would like to make a PCA score plot using ggplot2, and then convert the plot into interactive plot using plotly.

What I want to do is to add a frame (not ellipse using stat_ellipse, I know it worked).

My problem is that when I try to use sample name as tooltip in ggplotly, the frame will disappear. I don't know how to fix it.

Below is my code

library(ggplot2)
library(plotly)
library(dplyr)

## Demo data
dat <-  iris[1:4]
Group <- iris$Species

## Calculate PCA
df_pca <- prcomp(dat, center = T, scale. = FALSE)
df_pcs <- data.frame(df_pca$x, Group = Group)
percentage <-round(df_pca$sdev^2 / sum(df_pca$sdev^2) * 100, 2)
percentage <-paste(colnames(df_pcs),"(", paste(as.character(percentage), "%", ")", sep = ""))

## Visualization
Sample_Name <- rownames(df_pcs) 
p <- ggplot(df_pcs, aes(x = PC1, y = PC2, color = Group, label = Sample_Name)) +
  xlab(percentage[1]) +
  ylab(percentage[2]) +
  geom_point(size = 3)

ggplotly(p, tooltip = "label")

Until here it works! You can see that sample names can be properly shown in the ggplotly plot.

enter image description here

Next I tried to add a frame

## add frame 
hull_group <- df_pcs %>%
  dplyr::mutate(Sample_Name = Sample_Name) %>%
  dplyr::group_by(Group) %>%
  dplyr::slice(chull(PC1, PC2))
p2 <- p +
  ggplot2::geom_polygon(data = hull_group, aes(fill = Group), alpha = 0.1)

You can see that the static plot still worked! The frame is properly added.

enter image description here

However, when I tried to convert it to plotly interactive plot. The frame disappeared.

ggplotly(p2, tooltip = "label")

Thanks a lot for your help.

enter image description here


Solution

  • It works if you move the data and mapping from the ggplot() call to the geom_point() call:

    p2 <- ggplot() +
      geom_point(data = df_pcs, mapping = aes(x = PC1, y = PC2, color = Group, label = Sample_Name), size = 3) +
      ggplot2::geom_polygon(data = hull_group, aes(x = PC1, y = PC2, fill = Group, group = Group), alpha = 0.2)
    
    ggplotly(p2, tooltip = "label")
    

    working

    You might want to change the order of the geom_point and geom_polygon to make sure that the points are on top of the polygon (this also affects the tooltip location).