Add legends to ggplot2 - r

I am trying to add legend on ggplot2.
When I use the following codes, I get the following plot.
ggplot() +
geom_bar(data = profitCountries, aes(y = (revenue), x = residence), stat="identity",
fill="darkgreen", color = "black") +
geom_bar(data = profitCountries, aes(y = -(total_spend), x = residence), stat="identity",
fill="red", color = "black") +
geom_line(data = profitCountries, aes(y = total_profit, x = residence, group = 1), size = 1.5,
color = "blue" ) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') + ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') + theme_grey()
As suggested in other posts, I added color inside aes(). When I try to do that using the following code, I get the following plot.
ggplot() +
geom_bar(data = profitCountries, aes(y = (revenue), x = residence, fill="darkgreen"), stat="identity",
color = "black") +
geom_bar(data = profitCountries, aes(y = -(total_spend), x = residence, fill="red"), stat="identity",
color = "black") +
geom_line(data = profitCountries, aes(y = total_profit, x = residence, group = 1, color = "blue"),
size = 2 ) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') + ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') + theme_grey()
In the second plot, the colors change and two legends are created. Is there anyway to solve this?

You are currently mapping the character vector green to a manual scale whose colors are automatically determined.
You probably want
ggplot(profitCountries, aes(residence)) +
geom_bar(aes(y = (revenue), fill="Revenue"), stat="identity",
color = "black") +
geom_bar(aes(y = -(total_spend), fill="Campaign Spending"), stat="identity",
color = "black") +
geom_line(aes(y = total_profit, group = 1, color = "Net"), size = 2) +
scale_y_continuous(breaks = seq(-500000,500000,100000), limits=c(-500000, 500000) ) +
xlab('Countries') +
ggtitle('Campaign spending and revenue by countries') +
ylab('Campaign spending Revenue') +
theme_grey() +
scale_fill_manual(values = c("Revenue" = "darkgreen", "Campaign Spending" = "red")) +
scale_color_manual(values = c("Net" = "blue"))

Related

How to use loop with geom_vline and facet_wrap?

I have data similar to the one I've created below:
set.seed(42)
dates <- seq.Date(as.Date("2012-08-01"), as.Date("2014-08-30"), "day")
n <- length(dates)
dat <- data.frame(date = dates,
category = rep(LETTERS[1:4], n/2),
daily_count = sample(18:100, n, replace=TRUE))
#following to be used for creating dotted lines; highlighting a certain point for each category
point_dates <- sample(seq.Date(as.Date("2012-08-01"), as.Date("2014-08-30"), "month"),4)
category_name <- list("A", "B", "C", "D")
I am creating a boxplot for each category using facet_wrap, and point_dates are important for me as they shows the point of interest in each boxplot. This is how I am creating the plot:
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
sapply(point_dates[[1]], function(xint) geom_vline(data=filter(dat,
category==category_name[[1]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[2]], function(xint) geom_vline(data=filter(dat,
category==category_name[[2]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[3]], function(xint) geom_vline(data=filter(dat,
category==category_name[[3]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
sapply(point_dates[[4]], function(xint) geom_vline(data=filter(dat,
category==category_name[[4]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))+
facet_wrap(~category, nrow = 2)
And this is the output of the code:
The plot is being created just fine. My question is, is there any better way (loop may be?) that would help me get rid of writing sapply multiple times. Because the number of categories may change (increase/decrease), that would be to change the code everytime.
Any guidance please?
I'm not sure that this is the best way, but you could do all of them in one go using map2 from tidyr. This would save you time from having to write out individual sapply.
library(tidyverse)
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"),
linetype=1, colour="red", size = 0.5)+
map2(point_dates, category_name,
~geom_vline(data=filter(dat, category==.y),
aes(xintercept = .x),
linetype=3, colour="black", size = 1))+
facet_wrap(~category, nrow = 2)
You can use map() to iterate the calls to sapply():
ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
map(seq_along(unique(dat$category)), ~sapply(point_dates[[.]], function(xint) geom_vline(data=filter(dat,
category==category_name[[.]]),aes(xintercept = xint),
linetype=3, colour="black", size = 1))) +
facet_wrap(~category, nrow = 2)
If i got it correct, you have already defined the dates for each group. So make the first plot:
library(ggplot2)
library(tsibble)
g = ggplot(dat) +
geom_boxplot(aes(y = daily_count,
x = yearmonth(date),
group = paste(yearmonth(date), category),
fill = category)) +
labs(x = 'Month & Year',
y = 'Count',
fill = "Category") +
theme_bw() +
theme(axis.text=element_text(size=10),
axis.title=element_text(size=10),
legend.position="none") +
geom_vline(xintercept = lubridate::ymd("2013-08-23"), linetype=1, colour="red", size = 0.5)+
facet_wrap(~category, nrow = 2)
You just need to provide a new data frame and call geom_vline:
tmp = data.frame(category=unlist(category_name),date=point_dates)
g + geom_vline(data=tmp,aes(xintercept = date),
linetype=3, colour="black", size = 1)

How to scale a Geom_bar to be in line with an overlaid line graph in R ggplot

I am trying to overlay a bar chart with a line graph on a single plot with ggplot in R. My line graph works fine but the data are much larger than the data for the bar chart component.
How could I use an additional scale for this bar chart or do something that will get this to look nice all in one graph.
Here is my plot code thus far:
chart <- data.frame("QuantileName" = 1:5, "AvgLoss" = c(100, 500, 1000, 2500, 3000), "AvgFactor" = c(1.0, 1.1, 1.3, 1.4, 1.5))
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5), breaks = seq(1, 5)) +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_bar(aes(y = AvgFactor, colour = "AvgFactor" ), stat = "identity") +
geom_text(aes(y = AvgLoss, label = round(AvgLoss)), position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"), values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5))
Plot
Thank you for any help!
Essentialy, multiply your AvgFactor variable by a number
+ geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ), stat = "identity")
and set
+ scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
so your plot code would look like
Plot <- ggplot(chart, aes(x = 1:5)) +
scale_x_continuous(name = "Quintile", limits = c(0, 5 + .5),
breaks = seq(1, 5)) +
geom_bar(aes(y = AvgFactor*1000, colour = "AvgFactor" ),
stat = "identity") +
geom_line(aes(y = AvgLoss, colour = "AvgLoss")) +
geom_text(aes(y = AvgLoss,
label = round(AvgLoss)),
position = position_nudge(x = .3)) +
geom_point(aes(y = AvgLoss)) +
ylab("AvgLoss") +
scale_colour_manual("",breaks = c("AvgLoss","AvgFactor"),
values = c("AvgLoss" = "red", "AvgFactor" = "grey")) +
ggtitle("Quintile Plot") +
theme(plot.title = element_text(hjust=0.5)) +
scale_y_continuous(sec.axis = sec_axis(~ ./1000, name = "AvgFactor"))
However, I think it is probably more elegant to avoid secondary axes whenever possible.
It may be useful to know that geom_col(...) is shorthand for geom_bar(..., stat = 'identity')

ggplot legend / label change with various guides

I am trying to change the labels of a legend on a ggplot where I have legends for 2 aes.
With scale_file_manual, it works, but for one of the two legends only. I guess I should use "guides" that I already used to remove the titles and also remove legend for a 3rd aes, but I do not manage to do it.
Do you have a solution?
Here is my code :
p <- ggplot(data, aes(x = Nb))
p + geom_ribbon(aes(ymin = Sandwich.min, ymax = Sandwich.max, fill = 'grey70',alpha=0.8)) +
geom_ribbon(aes(ymin = Assiette.min, ymax = Assiette.max, fill = '#6495ED80',alpha=0.8)) +
geom_line(aes(y = Pizza, col = '#FF7F24')) +
geom_line(aes(y = Sushis, col = '#228B22')) +
labs(title = "Business lunch cost by number of participants",
x = "Number of participants",
y = "Price (Euros)") +
scale_x_continuous(breaks=seq(1,20,1)) +
scale_y_continuous(breaks = seq(0,300,50)) +
theme_light() +
theme(plot.title = element_text(size = 12, hjust = 0.5)) +
guides(alpha = FALSE, colour = guide_legend(" "), fill = guide_legend(" ")) +
scale_fill_manual(
values=c('#6495ED80','grey70'),
labels=c("Assiettes","Sandwiches"))

Control colour of geom_text_repel

I would like to change the colour of one of my ggrepel labels to black. I have tried to override the inheritance by specifying ...geom_text_repel(...colour='black') but that doesn't seem to work.
My attempt at a fix to the problem is in the second geom_text_repel function (below).
N.B. If there is a way to control the colour of individual geom_text_repel elements, rather than having to call the function twice, I would prefer that.
library("tidyverse")
library("ggthemes")
library("ggrepel")
df1 <- gather(economics, variable_name, observation, -date) %>%
rename(period = date) %>%
filter(variable_name == 'psavert')
df2 <- gather(economics, variable_name, observation, -date) %>%
rename(period = date) %>%
filter(variable_name == 'uempmed')
ggplot(df1, aes(x = period, y = observation, colour = variable_name)) +
geom_line() +
geom_line(data = df2, colour = 'black', size = .8) +
geom_text_repel(
data = subset(df1, period == max(as.Date(period, "%Y-%m-%d"))),
aes(label = variable_name),
size = 3,
nudge_x = 45,
segment.color = 'grey80'
) +
geom_text_repel(
data = subset(df2, period == max(as.Date(period, "%Y-%m-%d"))),
aes(label = variable_name, colour = 'black'), #How do I set the colour of the label text to black?
size = 3,
nudge_x = 45,
segment.color = 'grey80'
) +
scale_y_continuous(labels = scales::comma) +
theme_minimal(base_size = 16) +
scale_color_tableau() +
scale_fill_tableau() +
theme(legend.position = 'none') +
labs(x="", y="", title = "Economic Data") +
scale_x_date(limits = c(min(df1$period), max(df1$period) + 1200))
Do the same thing you did in your geom_line() layer. You want to set a color, not a mapping. Make colour = 'black' an argument to geom_text_repel(), not aes().
ggplot(df1, aes(x = period, y = observation, colour = variable_name)) +
geom_line() +
geom_line(data = df2, colour = 'black', size = .8) + # just like this layer
geom_text_repel(
data = subset(df1, period == max(as.Date(period, "%Y-%m-%d"))),
aes(label = variable_name),
size = 3,
nudge_x = 45,
segment.color = 'grey80'
) +
geom_text_repel(
data = subset(df2, period == max(as.Date(period, "%Y-%m-%d"))),
aes(label = variable_name) # don't assign it here,
size = 3,
nudge_x = 45,
segment.color = 'grey80',
colour = "black" # assign it here
) +
scale_y_continuous(labels = scales::comma) +
theme_minimal(base_size = 16) +
scale_color_tableau() +
scale_fill_tableau() +
theme(legend.position = 'none') +
labs(x="", y="", title = "Economic Data") +
scale_x_date(limits = c(min(df1$period), max(df1$period) + 1200))
Note that now the first line AND text are now both set manually to "black", so the automatic variable assignment will start over with next line (and text). If you want to set that manually to a different color, you can use the same strategy (set it as an argument to the geom, not as an argument to aes

R - Name of each bar in ggplot2

I would like to have the name of each bar under each bar (in my case the names are "Round" and they happen to be 1, 2, ... 12)
Here is my current code:
ggplot(data=draft1, aes(x = Round, y = mean.age)) +
geom_bar(stat = "identity", fill = "steelblue", color = "black", width = 0.7) +
ylab("Average age of retirement") + ylim(c(0,40)) +
ggtitle("Average age of retirement by rounds of all players") +
geom_text(aes(label = mean.age), position=position_dodge(width=0.9), vjust = -0.5)
Here is the current output:
set your Round to be a factor
ggplot(data=draft1, aes(x = factor(Round), y = mean.age)) +
Or use scale_x_continuous()
ggplot(data=draft1, aes(x = Round, y = mean.age)) +
... +
scale_x_continuous(breaks=(seq(1:12)))
Just add a discrete scale to x:
library(ggplot2)
draft1 = data.frame(Round = seq(1, 12), mean.age = sample(29:32))
ggplot(data=draft1, aes(x = Round, y = mean.age)) +
geom_bar(stat = "identity", fill = "steelblue", color = "black", width = 0.7) +
ylab("Average age of retirement") + ylim(c(0,40)) +
ggtitle("Average age of retirement by rounds of all players") +
geom_text(aes(label = mean.age), position=position_dodge(width=0.9), vjust = -0.5) +
scale_x_discrete()

Resources