8

Say I have this example data frame

set.seed(12345)
n1 <- 3
n2 <- 10
n3 <- 60

times <- seq(0, 100, 0.5)

individual <- c(rep(1, n1), 
                rep(2, n2), 
                rep(3, n3))

events <- c(sort(sample(times, n1)),
            sort(sample(times, n2)),
            sort(sample(times, n3)))

df <- data.frame(individual = individual, events = events)

Which gives

> head(df, 10)
   individual events
1           1   72.0
2           1   75.5
3           1   87.5
4           2    3.0
5           2   14.5
6           2   16.5
7           2   32.0
8           2   45.5
9           2   50.0
10          2   70.5

I would like to plot a cumulative step graph of the events so that I get one line per individual which goes up by 1 each time an event is "encountered".

So, for instance individual 1 will be 0 up to 72.0, then go up to 1, until 75.5 when it becomes 2 and up to 3 at 87.5 to the end of the graph.

What would be the easiest way to do that?

nico
  • 50,859
  • 17
  • 87
  • 112
  • Does that `df$counter <- ave(df$individual, df$individual, FUN = seq_along)` help? Not sure how you want your graph to look like but this should give you the "event count" – vaettchen Oct 27 '12 at 09:41
  • @vaettchen: yes it does! – nico Oct 27 '12 at 10:41

3 Answers3

6
df$step <- 1

library(plyr)
df <- ddply(df,.(individual),transform,step=cumsum(step))

plot(step~events,data=df[df$individual==1,],type="s",xlim=c(0,max(df$events)),ylim=c(0,max(df$step)),xlab="time",ylab="step")
lines(step~events,data=df[df$individual==2,],type="s",col=2)
lines(step~events,data=df[df$individual==3,],type="s",col=3)

step plot

Roland
  • 127,288
  • 10
  • 191
  • 288
  • Great! I love base graphics answers :) It would be perfect if there was a way to start the graphs from 0 (I guess I could simply add a 0 at the beginning). I guess I would use `apply` on `unique(df$Individual)` to do the plot in one function call. – nico Oct 27 '12 at 11:45
  • Many thanks. I didn't know that the `type="s"` argument is valid for `lines` and it is very handful. – Pavel Razgovorov Apr 08 '20 at 10:36
6

There is also the stepfun function in the stats package. Using that, you could use the plot method for that object class:

sdf <- split(df, individual)

plot(1, 1, type = "n", xlim = c(0, max(events)), ylim = c(0, max(table(individual))),
  ylab = "step", xlab = "time")

sfun <- lapply(sdf, function(x){
    sf <- stepfun(sort(x$events), seq_len(nrow(x) + 1) - 1)
    plot(sf, add = TRUE, col = unique(x$individual), do.points = FALSE)
})

enter image description here

BenBarnes
  • 19,114
  • 6
  • 56
  • 74
5

Use ggplot2:

library(ggplot2)

# Add step height information with sequence and rle
df$step <- sequence(rle(df$individual)$lengths)

# plot
df$individual <- factor(df$individual)
ggplot(df, aes(x=events, group=individual, colour=individual, y=step)) + 
  geom_step()

enter image description here

Andrie
  • 176,377
  • 47
  • 447
  • 496
  • This is exactly what I was looking for. I will wait a couple of days before accepting this to see if there are other answers (I would like to see an answer using base graphics). – nico Oct 27 '12 at 10:38