Reputation: 1445
I have the following dataset:
incidents.pct <- data.frame(
measure=c("Total Events (%)", "Security Events (%)", "Filtered (%)", "Tickets (%)"),
high=c(100,100,100,100),
mean=c(45,40,50,30),
low=c(25,20,10,5),
target=c(55,40,45,35),
value=c(50,45,60,25))
That I use to create the following "bullet like" graph.
g <- ggplot(incidents.pct) +
geom_bar(aes(measure, high), fill="goldenrod2", stat="identity", width=0.5, alpha=0.2) +
geom_bar(aes(measure, mean), fill="goldenrod3", stat="identity", width=0.5, alpha=0.2) +
geom_bar(aes(measure, low), fill="goldenrod4", stat="identity", width=0.5, alpha=0.2) +
geom_point(aes(measure, target), colour="red", size=2.5)
This works, however I would like to include a custom legend that explains the colours. So just a colour sign with fe "low", "medium", "value" etc...
Any advise on how to include this?
Upvotes: 2
Views: 783
Reputation: 11983
Another option could be to reshape your data before plotting.
library(ggplot2)
#reshape data for plotting
library(tidyverse)
df <- incidents.pct %>%
gather(fe, fe_value, -measure, -target, -value)
df$fe <- factor(df$fe, levels=c("high", "mean", "low"))
ggplot(df, aes(x=measure, y=fe_value, fill=fe)) +
geom_bar(stat="identity", alpha=0.3) +
scale_fill_manual(values=c("goldenrod2", "goldenrod3", "goldenrod4")) +
geom_point(aes(measure, target), colour="red", size=2.5) +
theme_bw()
#sample data
> dput(incidents.pct)
structure(list(measure = structure(c(4L, 2L, 1L, 3L), .Label = c("Filtered (%)",
"Security Events (%)", "Tickets (%)", "Total Events (%)"), class = "factor"),
high = c(100, 100, 100, 100), mean = c(45, 40, 50, 30), low = c(25,
20, 10, 5), target = c(55, 40, 45, 35), value = c(50, 45,
60, 25)), .Names = c("measure", "high", "mean", "low", "target",
"value"), row.names = c(NA, -4L), class = "data.frame")
Upvotes: 1
Reputation: 2101
Seems that I'm a bit late and @Z.Lin's answer is just fine, but I post mine as well because I think it points out the nice property of ggplot2
, namely the use of long data. Once you have your data in a tidy form, it is easy to print (yes, it takes more lines to make transform the data ;-)):
incidents.pct %>%
# ggplot2 likes long data:
gather(key = key, value = val, high, mean, low) %>%
# give nice order to factors:
mutate(key = factor(key, levels = c("high", "mean", "low"))) %>%
# arrange and group to take difference such that we can stack the values (sum up to 100):
arrange(measure, desc(key)) %>%
group_by(measure) %>%
mutate(val = val-ifelse(is.na(lag(val)), 0, lag(val))) %>%
# plot it, giving aes in ggplot, not necessarily below:
ggplot(aes(x = measure, y = val, fill = key)) +
# use geom_col if you want to use identity anyway:
geom_col(width = .5, alpha = .2) +
# just change the y-value in the aes, don't add it to legend:
geom_point(aes(y = target), colour = "red", size = 2.5, show.legend = FALSE) +
# now define your colours:
scale_fill_manual(values = c("goldenrod2", "goldenrod3", "goldenrod4"))
Upvotes: 0
Reputation: 29125
In ggplot, a legend is automatically generated for an aesthetic option if it's inside aes()
. So the following workaround with scale_fill_manual()
will give you a legend:
ggplot(incidents.pct) +
geom_col(aes(measure, high, fill = "high"), width=0.5, alpha=0.2) +
geom_col(aes(measure, mean, fill = "mean"), width=0.5, alpha=0.2) +
geom_col(aes(measure, low, fill = "low"), width=0.5, alpha=0.2) +
geom_point(aes(measure, target), colour="red", size=2.5) +
scale_fill_manual(name = "Legend",
values = c("high" = "goldenrod2",
"mean" = "goldenrod3",
"low" = "goldenrod4"),
breaks = c("high", "mean", "low"))
(Incidentally, geom_col()
is equivalent to geom_bar(stat = "identity")
, & looks neater.
I would caution against using low alpha value with overlapping bars, however, as the legend's colours won't match the plot's colours exactly. It would be cleaner to pick three lighter shades, and leave alpha as 1.
Upvotes: 5