17

I'm trying to draw a plot with several curves in it. The x-axis are not numerical values, but Strings.

This works fine (like in how to plot all the columns of a data frame in R):

require(ggplot2)
df_ok <- rbind(data.frame(x=4:1,y=rnorm(4),d="d1"),data.frame(x=3:1,y=rnorm(3),d="d2"))
ggplot(df_ok, aes(x,y)) + geom_line(aes(colour=d))

But my data looks like this:

require(ggplot2)
df_nok <- rbind(data.frame(x=c("four","three","two","one"),y=rnorm(4),d="d1"),data.frame(x=c("three","two","one"),y=rnorm(3),d="d2"))
ggplot(df_nok, aes(x,y)) + geom_line(aes(colour=d))

I get the error geom_path: Each group consist of only one observation. Do you need to adjust the group aesthetic?. Even though the graph lines do not appear, the axis are plotted, and the x-Axis contains the correct Labels - but also in wrong order.

Any idea how to plot this as easy as possible? (Also note the missing x-values for some series).

Community
  • 1
  • 1
fabb
  • 11,660
  • 13
  • 67
  • 111

3 Answers3

21

Your problem is that the x variable is a factor. So, change your data frame and make x a double:

df = rbind(data.frame(x=4:1,y=rnorm(4),d="d1"), 
           data.frame(x=3:1,y=rnorm(3),d="d2"))

Plot as normal

g = ggplot(df, aes(x,y)) + geom_line(aes(colour=d))

but alter the x-axis scaling explicitly:

g + scale_x_continuous(breaks=1:4, labels=c("one", "two", "three", "four")) 

To rename your variable, try something like:

x1 = factor(df_nok$x, 
            levels=c("one", "two", "three", "four"), 
            labels=1:4)
df$x1 = as.numeric(x1)
csgillespie
  • 59,189
  • 14
  • 150
  • 185
  • I'd love to not have to reshape my data. But if no one else has an idea, I will accept this answer. – fabb May 08 '12 at 10:50
  • 1
    Have you an idea how I easily could reshape my data to this form when I have got `df_nok` and a wanted order of `x`? – fabb May 08 '12 at 10:52
  • i would upvote you ten if i could. must remember `as.is=TRUE` pretty much all the time! Had a second problem problem was caused by date being character after setting `as.is=TRUE` but that was easily solved with an `as.Date()`. – ricardo May 10 '13 at 11:36
  • Aren't you just love R and Stack Overflow? Fantastic! – Jia Gao Jan 18 '18 at 00:57
7

You can convince ggplot to draw lines by adding a dummy group,

ggplot(df_nok, aes(x,y)) + geom_line(aes(colour=d, group=d))

Also see http://kohske.wordpress.com/2010/12/27/faq-geom_line-doesnt-draw-lines/

fabb
  • 11,660
  • 13
  • 67
  • 111
baptiste
  • 75,767
  • 19
  • 198
  • 294
  • 1
    This does not work correctly. It draws one line with coloured segments, but not 2 seperate lines. – fabb May 08 '12 at 10:31
  • It should be `group=d`, not `group=1`. – Brian Diggs May 08 '12 at 17:01
  • Great stuff! Now only the order is wrong anymore ("four","one","three","two"). Any quick help for that? – fabb May 08 '12 at 17:17
  • sorry i read this too quickly, glad you got a better answer. PS: the order can be changed by making `x` a factor with levels in the order you want them displayed. – baptiste May 08 '12 at 19:34
  • @baptiste: but it works fine with the trick Brian Diggs commented above (except for sort order)! Edit your answer above and earn an upvote! – fabb May 09 '12 at 07:56
4

Add in the group aesthetic (sort of redundant, I know, but much simpler than re-jigging the axis labels).

df_nok <- rbind(data.frame(x=c("four","three","two","one"),y=rnorm(4),d="d1"),data.frame(x=c("three","two","one"),y=rnorm(3),d="d2"))

ggplot(df_nok, aes(x,y, group=d)) + geom_line(aes(colour=d))

It's true your x-axis is still probably not in the order you want. As noted by @csgillespie you can fix this by making it into a factor

df_nok$x <- factor(df_nok$x, 
            levels=c("one", "two", "three", "four"), 
            labels=1:4)
Tom
  • 4,860
  • 7
  • 43
  • 55
  • 1
    Better a year late than never, right? Well anyway, this will be for people like me who stumble into this in the future. – Tom Aug 13 '13 at 05:00