Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
607 views
in Technique[技术] by (71.8m points)

r - Changing line color in ggplot based on slope

I have the following code which plots points and draw a line between them.

ggplot (data = subset(df, vowel == "O" & gender == "f"), aes (x = time, y = val, color = formant)) +
      geom_point()+
      geom_line(aes(group=interaction(formant, number)))

It produces this:

enter image description here

Is there a way to group these by color/line type for negative slopes vs. positive slopes of these lines?

edit: Here is my data:

number <- c(1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3)
formant <- c("F2", "F2", "F2", "F2", "F2", "F2", "F3", "F3", "F3", "F3", "F3", "F3")
time <- c(50, 50, 50, 99, 99, 99, 50, 50, 50, 99, 99, 99)
val <- c(400, 500, 600, 450, 550, 650, 300, 400, 500, 250, 350, 450)

I want to show movement of in the value of val over time grouped by formant and number. So when I implement the answer, it tells me I have an incompatible size, which I think has something to do with the fact that it's grouped by number.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You haven't provided sample data, so here's a stylized example. The general idea is that you create a variable that tests whether the slope is greater than zero and then map that to a colour aesthetic. In this case, I use the dplyr chaining operator (%>%) in order to add the slope on the fly within the call to ggplot. (I went to the trouble of calculating the slope, but you could just as well test whether value[t==2] > value[t==1] instead.)

library(dplyr)

# Fake data
set.seed(205)
dat = data.frame(t=rep(1:2, each=10), 
                 pairs=rep(1:10,2), 
                 value=rnorm(20), 
                 group=rep(c("A","B"), 10))

dat$value[dat$group=="A"] = dat$value[dat$group=="A"] + 6

ggplot(dat %>% group_by(pairs) %>%
         mutate(slope = (value[t==2] - value[t==1])/(2-1)),
       aes(t, value, group=pairs, linetype=group, colour=slope > 0)) +
  geom_point() +
  geom_line()

enter image description here

UPDATE: Based on your comment, it sounds like you just need to map number to an aesthetic or use faceting. Here's a facetted version using your sample data:

df = data.frame(number, formant, time, val)

# Shift val a bit
set.seed(1095)
df$val = df$val + rnorm(nrow(df), 0, 10)

ggplot (df %>% group_by(formant, number) %>%
          mutate(slope=(val[time==99] - val[time==50])/(99-50)), 
        aes (x = time, y = val, linetype = formant, colour=slope > 0)) +
  geom_point()+
  geom_line(aes(group=interaction(formant, number))) +
  facet_grid(. ~ number)

enter image description here

Here's another option that maps number to the size of the point markers. This doesn't look very good, but is just for illustration to show how to map variables to different "aesthetics" (colour, shape, size, etc.) in the graph.

ggplot (df %>% group_by(formant, number) %>% 
          mutate(slope=(val[time==99] - val[time==50])/(99-50)), 
        aes (x = time, y = val, linetype = formant, colour=slope > 0)) +
  geom_point(aes(size=number))+
  geom_line(aes(group=interaction(formant, number)))

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...