Home > Blockchain >  Add id labels to points above the limit line in ggplot
Add id labels to points above the limit line in ggplot

Time:10-06

I have a dataframe like this

id <- c(5738180,51845,167774,517814,1344920)
amount <- c(3.76765976,0.85195407,1.96821355,0.01464609,0.57378284)
outlier <- c("TRUE","FALSE","FALSE","FALSE","FALSE")
df.sample <- data.frame(id,amount,outlier) 

I am trying to plot the points and add an id label to any point that is above the limit. In this case (id=5738180)

I am plotting like this

library(tidyverse)    
library(ggplot2)
library(ggrepel)  # help avoid overlapping text labels
library(gridExtra) # adds custom table inside ggplot
library(scales)  # breaks and labels for axes and legends 
library(ggthemes)  # Adding desired ggplot themes

df.sample %>%
        ggplot(aes(x = as.numeric(row.names(df.sample)),
                   y = amount, label = as.character(id)))   
        geom_point(alpha = 0.6, position = position_jitter(w = 0.05, h = 0.0), 
                   aes(colour = (amount < 3)), size = 2)  
        geom_hline(aes(yintercept = 3, linetype = "Limit"), 
                   color = 'black', size = 1)        
        geom_text(aes(y = 3,x = amount[4],
                      label = paste("Limit = ", round(3, 3)),
                      hjust = 0, vjust = 1.5))  
        geom_text_repel(data          = subset(df.sample, outlier == 'TRUE'),
                        nudge_y       = 0.75,
                        size          = 4,
                        box.padding   = 1.5,
                        point.padding = 0.5,
                        force         = 100,
                        segment.size  = 0.2,
                        segment.color = "grey50",
                        direction     = "x")  
        geom_label_repel(data          = subset(df.sample, outlier == 'TRUE'),
                         nudge_y       = 0.75,
                         size          = 4,
                         box.padding   = 0.5,
                         point.padding = 0.5,
                         force         = 100,
                         segment.size  = 0.2,
                         segment.color = "grey50",
                         direction     = "x") 
      labs(title = "Outlier Detection",
           y = "amount",
           x = "")  
        theme_few()  
        theme(legend.position = "none",
              axis.text = element_text(size = 10, face = "bold"), 
              axis.title = element_text(size = 10, face = "bold"),
              plot.title = element_text(colour = "blue", hjust = 0.5,
                                        size = 15, face = "bold"),
              strip.text = element_text(size = 10, face = "bold"))  
        scale_colour_manual(values = c("TRUE" = "green","FALSE" = "red"))

I am running into an error "Error: Aesthetics must be either length 1 or the same as the data (1): x"

Can someone point me in the right direction?

CodePudding user response:

The issue is with geom_text_repel() and geom_label_repel(). You subset the data, which now only includes 1 row, but the aes() are inheriting from the original data which have 5 rows, hence the error. To fix this, subset the data outside of the ggplot() call, and change the aesthetics for it. You are also missing a after geom_label_repel() and the result below modifies the nudge_y to nudge_x and removes the geom_text_repel().

outliers <- subset(df.sample, outlier == TRUE) 

ggplot(data = df.sample, 
       aes(x = as.numeric(row.names(df.sample)),
           y = amount, 
           label = as.character(id)))   
  geom_point(alpha = 0.6, 
             position = position_jitter(w = 0.05, h = 0.0), 
             aes(colour = (amount < 3)), 
             size = 2)  
  geom_hline(aes(yintercept = 3, 
                 linetype = "Limit"), 
             color = 'black', 
             size = 1)        
  geom_text(aes(y = 3,x = amount[4],
                label = paste("Limit = ", 
                              round(3, 3)),
                hjust = 0, 
                vjust = 1.5))  
  geom_label_repel(data = outliers,
                   aes(x = as.numeric(rownames(outliers)),
                       y = amount,
                       label = amount),
                   nudge_x       = 0.75,
                   size          = 4,
                   box.padding   = 0.5,
                   point.padding = 0.5,
                   force         = 100,
                   segment.size  = 0.2,
                   segment.color = "grey50",
                   direction     = "x",
                   inherit.aes = F)  
  labs(title = "Outlier Detection",
       y = "amount",
       x = "")  
  theme_few()  
  theme(legend.position = "none",
        axis.text = element_text(size = 10, face = "bold"), 
        axis.title = element_text(size = 10, face = "bold"),
        plot.title = element_text(colour = "blue", hjust = 0.5,
                                  size = 15, face = "bold"),
        strip.text = element_text(size = 10, face = "bold"))  
  scale_colour_manual(values = c("TRUE" = "green","FALSE" = "red"))

enter image description here

  • Related