2
df<-data.frame(adjuster=c("Mary","Mary","Bob","Bob","Mary"), 
           date=as.Date(c("2012-1-1","2012-2-1","2012-3-1","2012-4-1","2012-5-1")), 
           total=c(10,15,25,15,20), paid=c(5,5,10,10,15))
ggplot(df)+geom_point(aes(x=date,y=total,color=adjuster,group=1))+
  geom_line(aes(x=date,y=paid,group=2,color="Paid"))+scale_color_discrete(name="Legend")+
  geom_line(aes(x=date,y=total,color=adjuster,group=1))

enter image description here

I want to force the "Paid" line to always be black, but let the other lines take the default colors provided by ggplot. How do I accomplish this?

Ben
  • 20,038
  • 30
  • 112
  • 189
  • 1
    Wouldn't it just be: `+ geom_line(aes(x=date, y=paid, color="black")) +` – IRTFM Nov 01 '13 at 22:59
  • That successfully sets color black, but it removes "Paid" from my legend – Ben Nov 01 '13 at 23:05
  • something like `scale_colour_manual(name="Legend", values=c("blue","green","black"))` doesn't use default colors, but does what you need right? – sckott Nov 01 '13 at 23:21
  • The only problem there is, the number of adjusters (i.e. Mary and Bob) varies. In other words, I need the colors of Mary and Bob to be dynamic because my next dataset may have Mary Bob and Sue. All my datasets will include a "Paid" value. – Ben Nov 01 '13 at 23:25
  • In that case you could add "Paid" as a separate layer, setting color of line to black – sckott Nov 01 '13 at 23:37
  • 1
    That's kind of what I figured. I tried something like that though, and again had problems with my legend. Could you whip something up to show me? – Ben Nov 01 '13 at 23:40

2 Answers2

4

Here is a possible solution that results in cleaner plotting code, more in the spirit of how ggplot2 is designed. The price is that your data needs to be rearranged a bit. I've also used some additional code to dynamically generate a named character vector of color values. Thanks to @John Colby for gg_color_hue().

The data are now in 'long-form', with all x-values and y-values in two columns. Additionally, there are two grouping factors, to separate the semantics of drawing the lines versus coloring the lines and points:

col_group line_group       date total
     Mary   Adjuster 2012-01-01    10
     Mary   Adjuster 2012-02-01    15
      Bob   Adjuster 2012-03-01    25
      Bob   Adjuster 2012-04-01    15
     Mary   Adjuster 2012-05-01    20
     Paid       Paid 2012-01-01     5
     Paid       Paid 2012-02-01     5
     Paid       Paid 2012-03-01    10
     Paid       Paid 2012-04-01    10
     Paid       Paid 2012-05-01    15

dat <- data.frame(col_group=c("Mary","Mary","Bob", "Bob", "Mary",
                              "Paid","Paid","Paid","Paid","Paid"),
                  line_group=c("Adjuster","Adjuster","Adjuster","Adjuster","Adjuster",
                               "Paid","Paid","Paid","Paid","Paid"), 
                  date=as.Date(c("2012-1-1","2012-2-1","2012-3-1","2012-4-1","2012-5-1",
                                 "2012-1-1","2012-2-1","2012-3-1","2012-4-1","2012-5-1")), 
                  total=c(10,15,25,15,20,
                          5, 5, 10,10,15))

# Color generating function found here:
# http://stackoverflow.com/questions/8197559/emulate-ggplot2-default-color-palette
gg_color_hue <- function(n) {
  hues = seq(15, 375, length=n+1)
  hcl(h=hues, l=65, c=100)[1:n]
}

# Dynamically generate default color values, but have Paid="black".
adj_names = sort(setdiff(unique(dat$col_group), "Paid"))
values = gg_color_hue(length(adj_names))
names(values) = adj_names
values = c(values, c(Paid="black"))

library(ggplot2)
plot1 <- ggplot(dat, aes(x=date, y=total, colour=col_group)) +
         geom_line(aes(group=line_group), size=1.2) +
         geom_point(size=2.8) +
         scale_colour_manual(values=values)

ggsave("plot1.png", plot=plot1, width=6, height=4.5, dpi=120)

enter image description here

bdemarest
  • 14,397
  • 3
  • 53
  • 56
2

This way Paid column is added as a separate layer, but that means it's not in the legend. I don't get why the column Paid would go in a legend with different levels of adjuster anyway. Why is that?

library(ggplot2)
df <- data.frame(adjuster=c("Mary","Mary","Bob","Bob","Mary"), 
           date=as.Date(c("2012-1-1","2012-2-1","2012-3-1","2012-4-1","2012-5-1")), 
           total=c(10,15,25,15,20), paid=c(5,5,10,10,15))

ggplot(df, aes(x=date,y=total,color=adjuster,group=1)) + 
  geom_point() +
  geom_line(aes(x=date, y=total, color=adjuster, group=1)) +
  geom_line(aes(x=date, y=paid, group=2), data=df, colour="black") +
  scale_color_discrete(name="Legend")

enter image description here

sckott
  • 5,755
  • 2
  • 26
  • 42
  • I just need some sort of annotation indicating that the black line is "paid". It doesn't have to be in the same legend as the adjusters, but I couldn't figure out how to add two legends. – Ben Nov 02 '13 at 15:39
  • Ah. I was thinking of reshaping your `data.frame` as the next answer but wasn't sure you wanted to do that... – sckott Nov 02 '13 at 15:48