alittleboy
alittleboy

Reputation: 10956

add point and line layers with customized legends in ggplot2

I have a question about plotting points and lines in the same plot using ggplot2. The codes for generating mock data are provided below:

library(ggplot2)
set.seed(111)
x = seq(1,10,length=10)
y1 = rnorm(10, 0, 0.1)
y2 = rnorm(10, 5, 0.1)
y3 = rnorm(10, 10, 0.3)
y4 = rnorm(10, 20, 0.4)
label = c(rep("Cat",10), rep("Dog", 10), rep("Owl", 10), rep("Eagle", 10))
dat1 = data.frame(cbind(x, y=y1))
dat2 = data.frame(cbind(x, y=y2))
dat3 = data.frame(cbind(x, y=y3))
dat4 = data.frame(cbind(x, y=y4))
dat = data.frame(rbind(dat1, dat2, dat3, dat4))
dat = cbind(dat, label)
dat

I use the following codes to generate the plot:

ggplot(dat, aes(x=x, y=y, colour=label)) + 

  geom_line(data=dat[dat$label=="Cat", ], aes(x=x, y=y, linetype=label)) +
  geom_line(data=dat[dat$label=="Dog", ], aes(x=x, y=y, linetype=label)) +

  geom_point(data=dat[dat$label=="Owl", ], aes(x=x, y=y, colour=label)) + 
  geom_point(data=dat[dat$label=="Eagle", ], aes(x=x, y=y, colour=label)) + 

  scale_color_manual("Animal", 
                     values = c("Cat" = "darkgreen",
                                "Dog" = "blue", 
                                "Owl" = "red",
                                "Eagle" = "cyan")) + 
  theme_bw() +
  scale_linetype_manual(values=c(1,2)) +
  scale_alpha_manual(values=c(0.8, 0.8, 0.2, 0.2)) +
  scale_size_manual(values=c(1.8, 1.8, 0.6, 0.6)) +
  theme(legend.key=element_blank(),
        legend.key.width = unit(3, "line"),
        legend.key = element_blank())

The current plot output looks like this: enter image description here

The following points need to be changed to get my desired plot:

  1. remove the "label" legend and only show the "Animal" legend
  2. for "Cat" and "Dog" legend, only show points, not lines; for "Owl" and "Eagle" legend, only show lines, not points
  3. the line types in legend should match those in the plot
  4. the order of the legend should be the same order as I specify the label: Cat, Dog, Owl and Eagle
  5. I hope the lines are ticker (width=2, for example), and the points are more transparent (alpha=0.4, for example)
  6. the legend position is inside the plot, not outside

    I appreciate your help/suggestions. Thank you!

Upvotes: 1

Views: 4450

Answers (1)

Didzis Elferts
Didzis Elferts

Reputation: 98419

As you are using different colors and linetypes then easiest way to get legend in order you need is to change order of level in you original data frame using function factor().

dat$label<-factor(dat$label,levels=c("Cat","Dog","Owl","Eagle"))

For the plot I would use only one call for the geom_point() and geom_line() and set the colour=, linetype= and shape= to label inside the aes() of ggplot(). Then using the scale_color_manual() set the colors you need, then with scale_linetype_manual() set linetypes 1 and 2 for the Cat and Dog and 0 (non-visible line) for other two levels. Inside scale_shape_manual() set values to NA for the Cat and Dog. In all manual scales use the same name to get only one legend. Alpha and size is changed inside the geom_point() and geom_line(). Legend position is udjusted with argument legend.postion= of function theme().

ggplot(dat, aes(x=x, y=y, colour=label,linetype=label,shape=label)) + 
      geom_point(alpha=0.4)+
      geom_line(size=2)+
      scale_color_manual("Animal", 
                         values = c("Cat" = "darkgreen",
                                    "Dog" = "blue", 
                                    "Owl" = "red",
                                    "Eagle" = "cyan"))    +
      scale_linetype_manual("Animal",values=c(1,2,0,0)) +
      scale_shape_manual("Animal",values=c(NA,NA,16,16))+
      theme_bw()+
      theme(legend.position=c(0.85,0.80))

enter image description here

Upvotes: 4

Related Questions