Urban Vagabond
Urban Vagabond

Reputation: 7732

how to get combined legend in ggplot2 when I have both geom_line and geom_hline

I have data as follows in a file wiki-hier.dat:

    1     2     5     10    20
2   80.77 80.76 80.77 80.77 80.77
3   83.06 83.11 83.11 83.11 83.11
4   84.40 84.46 84.43 84.44 84.43
5   85.24 85.31 85.31 85.31 85.31
6   85.92 86.03 86.02 86.02 86.01
7   86.41 86.56 86.55 86.55 86.55
8   86.62 86.76 86.77 86.77 86.77
10  87.13 87.32 87.32 87.32 87.32
12  87.50 87.71 87.68 87.69 NA
14  87.72 87.93 87.94 87.94 87.94
16  87.82 88.08 88.10 88.10 NA
18  87.87 88.15 88.17 88.17 88.17
20  87.93 88.22 88.23 88.23 88.23
24  88.10 88.39 88.40 88.41 88.40
28  88.10 88.46 88.47 88.47 88.47
32  88.12 88.46 88.49 88.49 NA
36  88.16 88.50 88.52 88.52 88.52
40  88.12 88.49 88.50 88.50 88.50
50  88.11 88.48 88.45 88.44 NA
60  87.90 88.26 88.25 88.25 NA
70  87.73 88.05 88.05 88.04 NA
80  87.60 87.89 87.90 87.89 NA
100 87.38 87.66 87.63 87.62 NA
120 87.01 87.23 87.23 87.23 NA
150 86.73 86.91 86.90 86.89 NA
200 86.04 86.14 86.08 86.06 NA
250 85.62 85.59 85.53 85.51 NA

I'm trying to plot this using ggplot2. My code is as follows:

library(ggplot2)
t = read.table("wiki-hier.dat", header=TRUE)
t$x = as.numeric(rownames(t))
data = data.frame(x = rep(t$x, 2), acc = c(t$X1, t$X2),
   beam = factor(rep(c(1,2), each=length(t$x))))
pdf("plotlines-wiki-hier-ggplot.pdf")
p = qplot(x, acc, data = data, geom = c("line", "point"),
    group = beam, color = beam, shape = beam, linetype = beam) +
  xlab("K-d subdivision factor") +
  ylab("Acc@161 (pct)") +
  geom_hline(aes(yintercept=84.49, linetype="Naive Bayes"), show_guide=TRUE) +
  scale_linetype_manual("beam", values = c(1,3,2))
print(p)
dev.off()

The problem is, I get two legends, and I only want one:

enter image description here

This one legend should have colors, shapes and linetypes in it for the keys "1" and "2".

How do I fix this?

The next-best thing would be to have two legends, one containing only the keys "1" and "2" and the other containing only the key "Naive Bayes".

Upvotes: 0

Views: 569

Answers (1)

user20650
user20650

Reputation: 25854

One way is to create another dataframe which you can map the aesthetics to similar to your main data.

#Your data

dat <- structure(list(X1 = c(80.77, 83.06, 84.4, 85.24, 85.92, 86.41, 
86.62, 87.13, 87.5, 87.72, 87.82, 87.87, 87.93, 88.1, 88.1, 88.12, 
88.16, 88.12, 88.11, 87.9, 87.73, 87.6, 87.38, 87.01, 86.73, 
86.04, 85.62), X2 = c(80.76, 83.11, 84.46, 85.31, 86.03, 86.56, 
86.76, 87.32, 87.71, 87.93, 88.08, 88.15, 88.22, 88.39, 88.46, 
88.46, 88.5, 88.49, 88.48, 88.26, 88.05, 87.89, 87.66, 87.23, 
86.91, 86.14, 85.59), X5 = c(80.77, 83.11, 84.43, 85.31, 86.02, 
86.55, 86.77, 87.32, 87.68, 87.94, 88.1, 88.17, 88.23, 88.4, 
88.47, 88.49, 88.52, 88.5, 88.45, 88.25, 88.05, 87.9, 87.63, 
87.23, 86.9, 86.08, 85.53), X10 = c(80.77, 83.11, 84.44, 85.31, 
86.02, 86.55, 86.77, 87.32, 87.69, 87.94, 88.1, 88.17, 88.23, 
88.41, 88.47, 88.49, 88.52, 88.5, 88.44, 88.25, 88.04, 87.89, 
87.62, 87.23, 86.89, 86.06, 85.51), X20 = c(80.77, 83.11, 84.43, 
85.31, 86.01, 86.55, 86.77, 87.32, NA, 87.94, NA, 88.17, 88.23, 
88.4, 88.47, NA, 88.52, 88.5, NA, NA, NA, NA, NA, NA, NA, NA, 
NA)), .Names = c("X1", "X2", "X5", "X10", "X20"), class = "data.frame", 
row.names = c("2",     "3", "4", "5", "6", "7", "8", "10", "12", "14", "16", 
"18", "20", "24", "28", "32", "36", "40", "50", "60", "70", "80", "100", 
"120", "150", "200", "250"))


dat$x = as.numeric(rownames(dat))
dat = data.frame(x = rep(dat$x, 2), acc = c(dat$X1, dat$X2),
                  beam = factor(rep(c(1,2), each=length(dat$x))))

# Create a new dataframe for your horizontal line
newdf <-  data.frame(x=c(0,max(dat$x)), acc=84.49, beam='naive')

# or of you want the full horizontal lines
# newdf <-  data.frame(x=c(-Inf, Inf), acc=84.49, beam='naive')

Plot

library(ggplot2)

ggplot(dat, aes(x, acc, colour=beam, shape=beam, linetype=beam)) +
  geom_point(size=4) + 
  geom_line() +
  geom_line(data=newdf, aes(x,acc)) +
  scale_linetype_manual(values =c(1,3,2)) +
  scale_shape_manual(values =c(16,17, NA)) +
  scale_colour_manual(values =c("red", "blue", "black"))

I used NA to suppress the shape in the naive legend

enter image description here

EDIT

After re-reading perhaps all you need is this

ggplot(dat, aes(x, acc, colour=beam, shape=beam, linetype=beam)) +
  geom_point(size=4) + 
  geom_line() +
  geom_hline(aes(yintercept=84.49), linetype="dashed")

Upvotes: 2

Related Questions