16

I can get a "filled" geom_line with either geom_ribbon or geom_area. Is there an equivalent for geom_step that doesn't require messing with polygons/barplots or creating the actual step points? Here is some sample data:

library(ggplot2)
set.seed(1)
df <- data.frame(
  x=rep(sort(sample(1:20, 5)), 3), 
  y=ave(runif(15), rep(1:3, each=5), FUN=cumsum),
  grp=letters[rep(1:3, each=5)]
)
ggplot(df, aes(x=x, y=y, color=grp)) + geom_step(position="stack")

Which produces:

enter image description here

Basically, I want exactly the same thing, but with filled areas. I know how to do this by actually creating the x/y values required for the steps and using geom_area, but I'm hoping there is something simpler.

BrodieG
  • 51,669
  • 9
  • 93
  • 146

3 Answers3

13

I know the question is a few years old, but I had the same problem today. For reference here's my solution. It's not more concise than the original answer, but may be easier to understand for some.

library(ggplot2)
library(dplyr)

df <- data.frame(x = seq(10), y = sample(10))

df_areaStep <- bind_rows(old = df, 
                         new = df %>% mutate(y = lag(y)),
                         .id = "source") %>%
               arrange(x, source)

ggplot(df, aes(x,y)) + 
  geom_ribbon(aes(x = x, ymin = 0, ymax = y), data = df_areaStep)

See this gist for longer version with comments.

Tobias Hotzenplotz
  • 1,177
  • 1
  • 11
  • 15
12

Here is the answer I was thinking of, for reference, but I'm hoping for something simpler/built-in if possible:

df2 <- rbind(
  df,
  transform(df[order(df$x),],
    x=x - 1e-9,  # required to avoid crazy steps
    y=ave(y, grp, FUN=function(z) c(z[[1]], head(z, -1L)))
) )
ggplot(df2, aes(x=x, y=y, fill=grp)) + geom_area()

enter image description here

BrodieG
  • 51,669
  • 9
  • 93
  • 146
0

Tobias's method above is excellent, it's beautifully clear and the longer explanation in the gist is super helpful. Thank you! There's one missing detail though: It doesn't work when you're trying to stack the grouped stepped areas as above (red, green and blue ribbons). The original poster's answer has a trick of putting the new point a tiny bit to the left of the step up to solve this problem, and can be used in Tobias's approach as well.

AnnaF
  • 41
  • 3