Home > Back-end >  How to highlight a specific region of a line changing linetype or size using ggplot
How to highlight a specific region of a line changing linetype or size using ggplot

Time:03-16

I have the following dataframe:

test = structure(list(Student = c("Ana", "Brenda", "Max", "Ana", "Brenda", 
"Max", "Ana", "Brenda", "Max"), Month = structure(c(1L, 1L, 1L, 
2L, 2L, 2L, 3L, 3L, 3L), .Label = c("January", "February", "March"
), class = "factor"), Grade = c(7L, 6L, 7L, 8L, 6L, 7L, 5L, 10L, 
10L), Change = c("February", "February", "February", "February", 
"February", "February", "February", "February", "February")), row.names = c(NA, 
-9L), class = "data.frame")

I plotted the grades of each student throughout the months, and wanted to know if there is a simple way to accentuate a specific part of each plotted line that would correspond to the period of time which showed the greatest shift in their grades (this info is already present in the dataset: column "Change". In this case, for all students it would be from February to March).

Trying to use a similar logic as presented This is how it looks

How do I fix it? Thanks in advance! n_n

CodePudding user response:

Don't specify the size in aes. Use the scale function

For another suggestion regarding line design see below.

test = structure(list(Student = c("Ana", "Brenda", "Max", "Ana", "Brenda", 
                                  "Max", "Ana", "Brenda", "Max"), Month = structure(c(1L, 1L, 1L, 
                                                                                      2L, 2L, 2L, 3L, 3L, 3L), .Label = c("January", "February", "March"
                                                                                      ), class = "factor"), Grade = c(7L, 6L, 7L, 8L, 6L, 7L, 5L, 10L, 
                                                                                                                      10L), Change = c("Februrary", "Februrary", "Februrary", "Februrary", 
                                                                                                                                       "Februrary", "Februrary", "Februrary", "Februrary", "Februrary"
                                                                                                                      )), row.names = c(NA, -9L), class = "data.frame")
## typo corrected
test$Change <- "February"

library(ggplot2)

ggplot(test, aes(x = Month, y = Grade, color = Student, group = Student))   
  geom_point()  
  ## don't specify size in aes
  geom_line(data = test, aes(size = Month == Change))  
  ## change the size scale
  scale_size_manual(values = c(`TRUE` = 2, `FALSE` = .8))

Another option might be to make use of the ggforce::geom_link functions, which interpolate aesthetics between two points.

library(ggforce)

ggplot(test, aes(x = Month, y = Grade, color = Student, group = Student))   
  geom_point()  
  geom_link2(data = test, aes(size = Grade, ), lineend = "round") 

This fails when trying to change the line type. In this case, use geom_segment instead - you will need some data transformation though.

library(tidyverse)

test %>%
  group_by(Student) %>%
  mutate(xend = lead(Month), yend = lead(Grade)) %>%
ggplot(aes(x = Month, y = Grade, color = Student, group = Student))   
  geom_point()  
  geom_segment(aes(xend = xend, yend = yend, linetype = Month == Change))  
  # need to specify your x
  scale_x_discrete(limits = unique(test$Month))
#> Warning: Removed 3 rows containing missing values (geom_segment).

CodePudding user response:

Changing the line width along its course is possible (as tjebo points out), but it rarely makes for a nice plot. A clearer way might be simply to add a coloured background over the area of interest:

library(hrbrthemes)
library(ggplot2)

ggplot(test, aes(x = Month, y = Grade, color = Student, group = Student))  
  geom_point(alpha = 0)  
  geom_rect(data = test[1,],
            aes(xmin = 'February', xmax = 'March', ymin = -Inf, ymax = Inf),
            color = NA, fill = 'deepskyblue4', alpha = 0.1)  
  geom_line(size = 1)  
  geom_point(shape = 21, fill = 'white', size = 3)  
  theme_minimal()  
  scale_color_manual(values = c('pink3', 'orange2', 'red4'))  
  theme_tinyhand()

enter image description here

  • Related