Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Coloring line segments in ggplot2

Tags:

r

ggplot2

Suppose I have following data for a student's score on a test.

set.seed(1)
df <- data.frame(question = 0:10,
                 resp = c(NA,sample(c("Correct","Incorrect"),10,replace=TRUE)), 
                 score.after.resp=50)
for (i in 1:10) {
  ifelse(df$resp[i+1] == "Correct",
         df$score.after.resp[i+1] <- df$score.after.resp[i] + 5, 
         df$score.after.resp[i+1] <- df$score.after.resp[i] - 5)
}
df

.

   question      resp score.after.resp
1         0      <NA>               50
2         1   Correct               55
3         2   Correct               60
4         3 Incorrect               55
5         4 Incorrect               50
6         5   Correct               55
7         6 Incorrect               50
8         7 Incorrect               45
9         8 Incorrect               40
10        9 Incorrect               35
11       10   Correct               40

I want to get following graph:

library(ggplot2)
ggplot(df,aes(x = question, y = score.after.resp)) + geom_line() + geom_point()

enter image description here

My problem is: I want to color segments of this line according to student response. If correct (increasing) line segment will be green and if incorrect response (decreasing) line should be red. I tried following code but did not work:

ggplot(df,aes(x = question, y = score.after.resp, color=factor(resp))) + 
  geom_line() + geom_point()

enter image description here

Any ideas?

like image 921
HBat Avatar asked Jun 12 '13 17:06

HBat


2 Answers

I would probably approach this a little differently, and use geom_segment instead:

df1 <- as.data.frame(with(df,cbind(embed(score.after.resp,2),embed(question,2))))
colnames(df1) <- c('yend','y','xend','x')
df1$col <- ifelse(df1$y - df1$yend >= 0,'Decrease','Increase')

ggplot(df1) + 
    geom_segment(aes(x = x,y = y,xend = xend,yend = yend,colour = col)) + 
    geom_point(data = df,aes(x = question,y = score.after.resp))

enter image description here

A brief explanation:

I'm using embed to transform the x and y variables into starting and ending points for each line segment, and then simply adding a variable that indicates whether each segment went up or down. Then I used the previous data frame to add the original points themselves.

Alternatively, I suppose you could use geom_line something like this:

df$resp1 <- c(as.character(df$resp[-1]),NA)
ggplot(df,aes(x = question, y = score.after.resp, color=factor(resp1),group = 1)) + 
    geom_line() + geom_point(color = "black")
like image 127
joran Avatar answered Nov 12 '22 06:11

joran


By default ggplot2 groups the data according to the aesthetics that are mapped to factors. You can override this default by setting group explicitly,

  last_plot() + aes(group=NA)
like image 11
baptiste Avatar answered Nov 12 '22 05:11

baptiste