Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2, color segment of geom_segment

I'm working on a rather elaborate plot of some indoor and outdoor activities, and I'm kinda stuck. I want to add colorize the minutes spent indoor/outdoor by (Xmin, Ymin, and Zmin) in the geom_segment step of my plot (see below). It's currently colored by only Zmin (used a continuous variable, which is kinda off).

I've pasted all the code in case others want to build something like this, I was initially inspired by this blog post.

Any help would be appreciated, thanks!

df <- data.frame(
  date = seq(Sys.Date(), len= 156, by="4 day")[sample(156, 26)],
  action = paste('Then', LETTERS[1:13], 'happed, which was not related to', LETTERS[14:26]),
  IndoorOutdoor = rep(c(-1,1), 13),
  Xmin = sample(90, 26, replace = T),
  Ymin = sample(90, 26, replace = T),
  Zmin = sample(90, 26, replace = T)
)

df$XYZmin <- rowSums(df[,c("Xmin", "Ymin", "Zmin")])*df$IndoorOutdoor

# install.packages("ggplot2", dependencies = TRUE)
require(ggplot2)

# step 1 
plot <- ggplot(df,aes(x=date,y=0))

# step 2, this is where I want to add 'more' color 
plot <- plot + geom_segment(aes(y=0,yend=XYZmin,xend=date, colour= Zmin))

# The text is added as follows
plot <- plot + geom_text(aes(y=XYZmin,label=paste(action, '\n this happed on ', date)),size=2.5,hjust=-.01, vjust=-.01, angle = 35)

# points at the end of the line segments
plot <- plot + geom_point(aes(y=XYZmin))

# #raw a vertical line
plot <- plot + geom_hline(y=0,size=1,color='purple')

#drawing the actual arrow
# plot <- plot + geom_segment(x=2011.4,xend=2012.2,y=.2,yend=0,color='purple',size=1) + geom_segment(x=2011.4,xend=2012.2,y=-.2,yend=0,color='purple',size=1)

plot <- plot + theme(axis.text.y = element_blank()) + ylab('') + xlab('')
plot + labs(title = "Timeline for when what happened")

enter image description here

like image 248
Eric Fail Avatar asked Jan 13 '23 23:01

Eric Fail


1 Answers

Here are two approaches. One constructs each line out of different geom_segments (I think this is closer to what you were doing?) the other just uses geom_bar, which would be my preference (much more scaleable). I think there is an error when you build your data.frame - you create 56 rows when you make IndoorOutdoor, which makes problems later. I've changed that below.

set.seed(1234)
df <- data.frame(
  date = seq(Sys.Date(), len= 156, by="4 day")[sample(156, 26)],
  action = paste('Then', LETTERS[1:13], 'happed, which was not related to', LETTERS[14:26]),
  IndoorOutdoor = rep(c(-1,1), 13), #Change so there are only 26 rows
  Xmin = sample(90, 26, replace = T),
  Ymin = sample(90, 26, replace = T),
  Zmin = sample(90, 26, replace = T)
)

df$XYZmin <- rowSums(df[,c("Xmin", "Ymin", "Zmin")])*df$IndoorOutdoor
df[,8:10] <- df[,4:6]*df[,3] #Adding the sign to each X/Y/Z
names(df)[8:10] <- paste0(names(df)[4:6],"p") #to differentiate from your X/Y/Z
require(ggplot2)

For the geom_bar solution I then melt df so that a single value can be plotted, and fill mapped to the varialbe (Xmin etc)

df.m <- melt(df[,c(1:3,7:10)], measure.vars=c("Xminp", "Yminp", "Zminp"))
plot.alt <- ggplot(df.m, aes(date, value, fill=variable)) + 
  geom_bar(position="stack", stat="identity", width=0.5) + #width is just to make it look like yours
#All of this is from your original plot
  geom_text(aes(y=XYZmin,label=paste(action, '\n this happed on ', date)),size=2.5,hjust=-.01, vjust=-.01, angle = 35) + 

  geom_point(aes(y=XYZmin), show_guide=FALSE) +
  geom_hline(y=0,size=1,color='purple') +
  theme(axis.text.y = element_blank()) + ylab('') + xlab('') +
  labs(title = "Timeline for when what happened")
plot.alt

enter image description here

Alternatively, here is a way to build it up using geom_segment:

plot <- ggplot(df,aes(x=date)) +
#Three geom_segments 
  geom_segment(aes(y=0,yend=Xminp,xend=date), colour= "blue") +
  geom_segment(aes(y=Xminp,yend=Xminp + Yminp,xend=date), colour= "red") +
  geom_segment(aes(y=Xminp + Yminp,yend=Xminp + Yminp + Zminp,xend=date), colour= "green") +
#This is all from your plot
  geom_text(aes(y=XYZmin,label=paste(action, '\n this happed on ', date)),size=2.5,hjust=-.01, vjust=-.01, angle = 35) +
  geom_point(aes(y=XYZmin)) +
  geom_hline(y=0,size=1,color='purple') +
  theme(axis.text.y = element_blank()) + ylab('') + xlab('') +
  labs(title = "Timeline for when what happened")
plot

Hope that makes sense... let me know if it's not what you were after. enter image description here

like image 145
alexwhan Avatar answered Jan 19 '23 10:01

alexwhan