Plot stacked barplot with upper part with alpha - r

I want to plot a stacked bar where the upper part is colored in the same way but with alpha. The images below give an idea, what I want is to have the magma colors, but the upper part with alpha. I wonder if it helps more to have two plots and "stack" them together. The upper part (alpha) is the tam_loc variable in the dataset. That is rural areas.
If I put alpha in aes it produces the output, but I cannot manipulate the alpha degree. Further, if I do this the legend now has a bar (mean value) for non alpha values. See image
The data is here.
My code looks like this:
ggplot(locPCP, aes(reorder(x=NOMGEO, -mean),y=mean, fill=bin, alpha=tam_loc)) +
geom_bar(stat="identity") +
scale_fill_manual(labels = c("> 8", "3.5 - 4", "3 - 3.5", "2.5 - 3", "2 - 2.5", "< 2"),
values = c(state_colors[2:7])) +
scale_x_discrete(name="State") +
scale_y_continuous(name="Emissions per capita (t CO2eq/year)", limits=c(0, 15)) +
geom_hline(yintercept=pcp2015, linetype="dashed",
color = "black", size=1) +
geom_hline(yintercept=pcp2030, linetype="dashed",
color = "red", size=1) +
geom_hline(yintercept=pcp2018, linetype="dashed",
color = "blue", size=1) +
theme_classic() +
theme(legend.position="top",
legend.text = element_text(size=15, color="black"),
legend.title = element_text(size=15, color="black"),
axis.text.x = element_text(size=15, color="black", angle = 90, vjust = 0.2, hjust=1),
axis.text.y = element_text(size=15, color="black"),
axis.title.x = element_text(size=15, color="black", vjust=-1),
axis.title.y = element_text(size=15, color="black")) +
geom_errorbar(aes(ymax=meanS, ymin=meanS), colour="white", width=0.5, size=1) # http://www.cookbook-r.com/Graphs/Lines_(ggplot2)/

You would simply map alpha to tam_loc and specify a scale_alpha_manual scale. Specify guide = "none" inside the alpha scale if you don't want it to appear in the legend. If you want a guide without the horizontal bar, use key_glyph = draw_key_blank inside geom_errorbar, which is where this line is coming from.
Remember, every fill color has an alpha value. A completely solid color that you cannot see through has an alpha value of 1, and a completely invisible color has an alpha of 0. It becomes confusing when you start to talk about the upper parts of the bars "having alpha" - it's more accurate to say that the upper bars have a lower alpha value.
ggplot(locPCP, aes(reorder(x=NOMGEO, -mean), y = mean, fill = bin,
alpha = tam_loc)) +
geom_col() +
geom_hline(yintercept = pcp2015, linetype = "dashed",
color = "black", size = 1) +
geom_hline(yintercept = pcp2030, linetype = "dashed",
color = "red", size = 1) +
geom_hline(yintercept=pcp2018, linetype="dashed",
color = "blue", size = 1) +
geom_errorbar(aes(ymax = meanS, ymin = meanS), colour = "white",
width = 0.5, size = 1, key_glyph = draw_key_blank) +
scale_fill_manual(labels = c("> 8", "3.5 - 4", "3 - 3.5",
"2.5 - 3", "2 - 2.5", "< 2"),
values = c(state_colors[2:7])) +
scale_x_discrete(name = "State") +
scale_y_continuous(name = "Emissions per capita (t CO2eq/year)",
limits = c(0, 15)) +
scale_alpha_manual(values = c(0.5, 1), name = 'Location') +
theme_classic(base_size = 15) +
theme(legend.position = c(0.5, 1),
legend.box = 'vertical',
legend.direction = 'horizontal',
legend.justification = c(0.5, 1),
axis.text.x = element_text(angle = 90, vjust = 0.2, hjust = 1),
axis.text.y = element_text(size = 15, color="black"),
axis.title.x = element_text(vjust = -1))
Incidentally, you have some variables defined in your code that are not present in your question. I have guessed at them here.
state_colors <- viridisLite::magma(8)
pcp2015 <- 5
pcp2018 <- 3
pcp2030 <- 2.5

Related

How to fit the axis title with two lines in R?

I made one graph with 'two line' y-axis title using the code ylab(expression(paste()
Genotype <- c("CV1","CV2","CV1","CV2")
Category<- c("GN","GN","AGW","AGW")
mean <- c(1.47,1.66,0.98,0.93)
se<- c(0.10,0.20,0.03,0.06)
DataA<- data.frame(Genotype,Category,mean,se)
DataA
ggplot(data=DataA, aes(x=Genotype, y=mean, fill=Category))+
geom_bar(stat="identity",position="dodge", width = 0.7) +
geom_errorbar(aes(ymin= mean-se, ymax=mean + se), position=position_dodge(0.7),
width=0.2, size=1) +
scale_fill_manual(values= c ("Dark gray", "Cadetblue")) +
scale_y_continuous(breaks = seq(0,2,0.2), labels = scales::percent, limits = c(0,2)) +
geom_hline(yintercept=1, linetype="dashed", color = "Dark red", size=1.5) +
xlab("Cultivar") +
ylab(expression(paste("Value of thinning treatment \n relative to unthinning treatment"))) +
theme(axis.title = element_text (face = "plain", size = 15, color = "black"),
axis.text.x = element_text(size= 15),
axis.text.y = element_text(size= 15),
axis.line = element_line(size = 0.5, colour = "black"))+
windows(width=7, height=5)
The y-axis title was divided into two lines, but the whole title was not fitted inside the graph. Even though I adjust the width of graph size, it was not applied to the axis title.
Could you tell me how to fit the whole y-axis title inside the graph well, maintaining the size of axis title (i.e. font size= 15)?
Thanks,
One way would be to adjust the margins giving more space to the left.
library(ggplot2)
ggplot(data=DataA, aes(x=Genotype, y=mean, fill=Category))+
geom_bar(stat="identity",position="dodge", width = 0.7) +
geom_errorbar(aes(ymin= mean-se, ymax=mean + se), position=position_dodge(0.7),
width=0.2, size=1) +
scale_fill_manual(values= c ("Dark gray", "Cadetblue")) +
scale_y_continuous(breaks = seq(0,2,0.2), labels = scales::percent, limits = c(0,2)) +
geom_hline(yintercept=1, linetype="dashed", color = "Dark red", size=1.5) +
xlab("Cultivar") +
ylab(expression(paste("Value of thinning treatment \n relative to unthinning treatment"))) +
theme(axis.title = element_text (face = "plain", size = 15, color = "black"),
axis.text.x = element_text(size= 15),
axis.text.y = element_text(size= 15),
axis.line = element_line(size = 0.5, colour = "black")) +
theme(plot.margin=unit(c(1,0.5,0.5,1.2),"cm"))

Increase Vertical Spacing between Legend Key in ggplot2

How can I increase vertical spacing between legend keys:
p1 <- ggplot(data = HSS, mapping = aes(x = EVENT, y = HSS, fill = TIME)) +
geom_bar(stat = "identity",width=0.7, colour = "black", position = position_dodge(0.7)) +
scale_fill_manual("HSS", values = c("deepskyblue3", "indianred2"),
labels = c("1200 UTC (0.049)", "0000 UTC (0.031)")) + theme_bw()
p1 <- p1 + scale_y_continuous(expand = expansion(mult = c(0.0085, -0.085)),
limits = c(-0.03,0.5), breaks = c(-0.03,-0.01, 0.01, 0.03, 0.05, 0.07,0.09,0.11,0.13,0.15,0.17,
0.19, 0.21,0.23,0.25,0.27,0.29,0.31,0.33,0.45),
labels = c("-0.03","-0.01","0.01","0.03","0.05","0.07","0.09","0.11","0.13","0.15","0.17",
"0.19","0.21","0.23","0.25","0.27","0.29","0.31","0.33","0.45")) +
theme(axis.text.x=element_text(color = "black", size=12, face = "bold", angle=90, vjust=.5,
hjust=0.8)) +
theme(axis.text.y = element_text(color = "black", size=12, face = "bold"))
p1 <- p1 + theme( axis.line = element_line(colour = "black", size = 0.5, linetype = "solid")) +
labs( y = "HSS")
p1 <- p1 + theme(axis.title=element_text(colour = "blue2" ,size=14,face="bold", vjust = 0.1))
p1 <- p1 + theme(legend.position=c(0.98,0.98)) + theme(legend.title=element_blank(),
legend.text = element_text(face = "bold", size = "12"),
legend.box.background = element_rect(size=0.7, linetype="solid"),
legend.justification = c("right", "top"),
legend.box.margin = margin(1, 1, 1, 1)
)
p1
I tried using legend.key.height legend.spacing.y guide but it only stretched legend keys without adding space between them. Also how can I remove alternate lables (encircled) of Y-axis keeping tickmark with plot.
After browsing ggplot2's source code for a bit, I come to the conclusion that the legend.spacing.y is only applied when the byrow = TRUE as argument to the legend.
Simplied example below.
library(ggplot2)
ggplot(iris, aes(Sepal.Width)) +
geom_density(aes(fill = Species)) +
guides(fill = guide_legend(byrow = TRUE)) +
theme(legend.spacing.y = unit(1, "cm"))
With regards to the labels, just remove the values from the breaks argument in scale_y_continuous() that you don't want to show, you're already specifying them manually.

How to display values of a column inside bars of a bar chart

Using the code below, I could create the below graph. I would like to make some customization as follows:
1- drop the numbers from the beginning of labels in the legend (e.g.,4.Male NCG to Male NCG) but do not change the order of values
2- display the values of meanHLE_ inside the bars and define using a new legend
3-separate male and female categories in the graph
#my data
sample_label<-c("4.Male NCG","4.Male NCG","4.Male NCG",
"5.Male caregivers<14h/w","5.Male caregivers<14h/w",
"5.Male caregivers<14h/w","6.Male caregivers>=14h/w",
"6.Male caregivers>=14h/w","6.Male caregivers>=14h/w",
"7.Female NCG","7.Female NCG","7.Female NCG",
"8.Female caregivers<14h/w", "8.Female caregivers<14h/w",
"8.Female caregivers<14h/w", "9.Female caregivers>=14h/w",
"9.Female caregivers>=14h/w","9.Female caregivers>=14h/w")
Age_Group_<-c("50-51","60-61","70-71","50-51","60-61","70-71",
"50-51","60-61","70-71","50-51","60-61","70-71",
"50-51","60-61","70-71","50-51","60-61","70-71")
meanTLE_<-c(32.4,24,16.3,34.4,25.6,17.3,33.4,24.7,16.8,
36,26.8,18.1,37.3,27.9,18.8,36.6,27.3,18.5)
meanHLE_<-c(24.8,18.3,12.3,27.2,20.2,13.6,25.3,18.7,12.6,
28.8,21.4,14.4,30.7,22.9,15.4,29.1,21.6,14.5)
2.plot section
gender<-data.frame(sample_label,Age_Group_,meanTLE_,meanHLE_)
ggplot(gender, aes(x =Age_Group_, y = meanTLE_, fill=sample_label)) + geom_bar(stat ="identity", position = "dodge2") + #fill = "#B61E2E"
geom_text(
aes(label = meanTLE_),
vjust = 0,
colour = "black",
position = position_dodge(width=0.9),
fontface = "bold",
size=3,
angle = 90,
hjust = 0
) +ylim(0,50)+
labs(
x = "Age Groups",
y = "Total Life Expactacny",
face = "bold"
) +
# coord_flip() +
theme_bw() +
# scale_fill_manual(values=c("meanHLE_")) +
theme(legend.title=element_blank(),legend.text = element_text(face = "bold"),plot.title = element_text(
hjust = 0.5,
size = 15,
colour = "Black",
face = "bold"
),
plot.caption = element_text(hjust = 0, color = "black", face = "bold", size=12.5))
I think the plot below does most of what you indicated in your OP and comments. However, I think this plot is very busy and the patterns aren't as transparent as they could be, so I've added a couple of other options.
library(tidyverse)
pd = position_dodge(0.9)
gender %>%
mutate(sex=str_extract(sample_label, "Male|Female"),
sample_label=gsub(".*ale ", "", sample_label),
sample_label=fct_relevel(sample_label, "NCG")) %>%
ggplot(aes(x =Age_Group_, y = meanTLE_, fill=sample_label, group=sample_label)) +
# Dodge value labels and bars by same amount
geom_col(position = pd, width=0.85) +
geom_text(aes(label=sprintf("%1.1f", meanTLE_)), hjust=0,
colour = "black", fontface = "bold", size=3, angle = 90,
# Dodge value labels and bars by same amount
position = pd) +
geom_col(aes(y=meanHLE_), width=0.4, size=0.2, colour="grey50", fill="white", position=pd) +
geom_text(aes(label=sprintf("%1.1f", meanHLE_),
y=meanHLE_, colour=sample_label), position=pd,
colour = "black", fontface = "bold", size=3, angle = 90,) +
geom_text(data=. %>%
group_by(sex) %>%
filter(Age_Group_=="70-71", grepl(">=14", sample_label)) %>%
ungroup %>%
pivot_longer(starts_with("mean")), hjust=0, colour="grey30", size=3,
aes(x=3.5, y=value, label=gsub("mean(.*)_", "\\1", name))) +
facet_grid(cols=vars(sex)) +
scale_y_continuous(limits=c(0,41), expand=c(0,0)) +
expand_limits(x=3.9) +
scale_colour_manual(values=hcl(seq(15,375,length=4)[1:3], 100, 80)) +
labs(x = "Age Groups", y = "Total Life Expectancy") +
theme_bw() +
theme(legend.title=element_blank(),
legend.text = element_text(face = "bold"),
plot.title = element_text(hjust = 0.5, size = 15, colour = "Black", face = "bold"),
plot.caption = element_text(hjust = 0, color = "black", face = "bold", size=12.5))
The plot below gets rid of the bars and uses values as point markers. I've reshaped the data to long format so that we need only a single call to each geom to plot the values and we can generate a legend with a color mapping. I've added subtle lines just to guide the eye. If you want to remove them, set size=0 in geom_line. Don't get rid of the geom_line call, as it's necessary in order to generate the legend.
gender %>%
mutate(sex=str_extract(sample_label, "Male|Female"),
sample_label=gsub(".*ale ", "", sample_label)) %>%
pivot_longer(cols=starts_with("mean")) %>%
ggplot(aes(y=sample_label, x=value, colour=name, group=name)) +
geom_line(size=0.4, alpha=0.5) +
geom_text(aes(label=sprintf("%1.1f", value)),
fontface = "bold", size=3, show.legend=FALSE) +
facet_grid(rows=vars(sex, Age_Group_)) +
scale_x_continuous(limits=c(0,40), expand=c(0,0)) +
scale_colour_discrete(labels=c("Healthy", "Total")) +
labs(x = "Mean (years)",
title="Life expectancy by age, sex, and caregiver status") +
theme_bw() +
theme(legend.title=element_blank(),
axis.title.y=element_blank(),
legend.text = element_text(face = "bold"),
plot.title = element_text(hjust = 0.5, size = 15, face = "bold"),
plot.caption = element_text(hjust=0, color="black", face="bold", size=12.5),
strip.text.y=element_text(angle=0),
legend.position="bottom",
legend.box.margin=margin(t=-10)) +
guides(colour=guide_legend(override.aes=list(size=3, alpha=1)))
This version seems to me to be the most transparent regarding the key patterns in the data. The data value text labels overlap, so maybe dodging or using point markers would be more effective.
gender %>%
mutate(sex=str_extract(sample_label, "Male|Female"),
sample_label=gsub(".*ale ", "", sample_label)) %>%
pivot_longer(cols=starts_with("mean")) %>%
ggplot(aes(y=value, x=Age_Group_, colour=sample_label)) +
geom_line(aes(linetype=name, group=interaction(name, sample_label)),
size=0.6, alpha=0.3) +
geom_text(aes(label=sprintf("%1.1f", value)), size=3, show.legend=FALSE) +
facet_grid(cols=vars(sex)) +
scale_y_continuous(limits=c(0,40), expand=c(0,0)) +
scale_linetype_discrete(labels=c("Healthy", "Total")) +
labs(x = "Age Group", y="years",
colour="Caregiver Status", linetype="Life Expectancy Type",
title="Life expectancy by age, sex, and caregiver status") +
theme_bw() +
theme(legend.text = element_text(face = "bold"),
plot.title = element_text(hjust = 0.5, size = 15, face = "bold"),
plot.caption = element_text(hjust = 0, color = "black", face = "bold", size=12.5)) +
guides(linetype=guide_legend(reverse=TRUE, override.aes=list(size=1)),
colour=guide_legend(override.aes=list(size=1, alpha=1)))

Is there a way to specify certain geom_images to be placed on top in a dense scatterplot?

I'm using ggplot and gganimate to animate a scatterplot of college football teams. My audience specifically centers around one team, so I'm wondering if there's a way for me to ensure that that team is always on top, i.e. not buried under the other teams.
Source Code:
aB <- ggplot(cB, aes(x=PPP, y=C)) +
geom_image(image=cB$logo, asp = 16/9) +
labs(y="Efficency (3rd and 4th Down Conversion Rate)", x="Explosiveness (Points per Play)",
caption = "Figure: #stevenplai | Data: ESPN") +
theme_minimal() +
theme(
plot.title = element_text(size=70, face = "bold", family = "Helvetica"),
plot.subtitle = element_text(size=60, family = "Helvetica"),
axis.ticks = element_line(),
axis.text = element_text(size=30),
axis.title = element_text(size=40, family = "Helvetica"),
plot.caption = element_text(size=30)
) +
geom_vline(xintercept = mean(cB$PPP), linetype = "dashed", color = "#841617") +
geom_hline(yintercept = mean(cB$C), linetype = "dashed", color = "#841617") +
transition_states(Year,
transition_length = 2,
state_length = 3) +
ease_aes('cubic-in-out') +
ggtitle('FBS Offensive Factors - Explosiveness vs. Efficiency' ,
subtitle = 'Season: {closest_state}')

Add legend to ggplot histogram with different types of aesthetics

I want to add a legend to one of my plots, but I have different aesthetics and I never created a legend so I find it very difficult to determine how to build it.
One of my aesthetics is a fill code, which I added manually as a vector. The other aesthetic is a vertical line that I added with geom_vline.
From the graph below, there are three characteristics that I want to add to the legend: 1) The bars with color dark blue, 2) The bars with color light blue and 3) The vertical line.
Does anyone have a suggestion for me on how to code this efficiently?
#df
df <- data.frame(Time_Diff <- runif(1000, 0, 200))
# Show median, IQR range and outliers
colors <- c(rep("blue",3), rep("paleturquoise2",38))
bp_overall <- ggplot(data = df, aes(Time_Diff))
bp_overall +
geom_histogram(binwidth = 5, fill = colors) + #create histogram
ggtitle("Time Difference") +
xlab("Time in Days") +
ylab("Amount") +
geom_vline(xintercept = 3, linetype = "twodash", size = 1, colour= "darkblue") + #show median
scale_x_continuous(breaks = seq(0, 202, 10)) +
theme_light() +
theme(panel.grid.minor = element_blank(),
panel.border = element_blank(), #remove all border lines
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"), #add x-axis border line
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black")) + #add y-axis border line
theme(plot.title = element_text(family = windowsFont("Verdana"), color="black", size=14, hjust = 0.5)) +
theme(axis.title = element_text(family = windowsFont("Verdana"), color="black", size=12))
After the suggestion of Djork I arrived to the following script, which works and I am happy with. The only thing I am trying to accomplish now is to get the Legend to be one whole (Histogram Legend and Line Legend are combined into a coherent whole). Anyone has a suggestion?
# reformat data
set.seed(1)
df <- data.frame(runif(1000, 0, 200))
colnames(df) <- "Time_Diff"
bp_overall +
geom_histogram(data = subset(df, Time_Diff <= 12.5), aes(x = Time_Diff, fill="BAR BLUE"), binwidth = 5) + # subset for blue data, where aes fill is fill group 1 label
geom_histogram(data = subset(df, Time_Diff > 12.5), aes(x = Time_Diff, fill="BAR TURQUOISE"), binwidth = 5) + # subset for turquoise data, where aes fill is fill group 2 label
scale_fill_manual("Histogram Legend", values=c("blue", "paleturquoise2")) + # manually assign histogram fill colors
geom_vline(aes(xintercept = 3, colour="LINE DARK BLUE"), linetype="twodash", size = 1) + # where aes colour is vline label
scale_colour_manual("Line Legend", values="darkblue") + #removed legend title
scale_x_continuous(breaks = seq(0, 202, 10)) +
ggtitle("Time Difference") +
xlab("Time in Days") +
ylab("Amount") +
theme_light() +
theme(panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"),
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black"),
legend.position = c(0.95, 0.95),
legend.justification = c("right", "top"),
legend.box.just = ("right"))
I think #Jimbou's suggestion is preferable, but there is a work-around for creating legends artificially by assigning a character value to the geom_histogram aes fill value and geom_vline aes colour value, then setting colors in scale_fill_manual or scale_colour_manual.
However with this approach aes fill will only take one value (length 1) so you have to subset your df for the blue and turquoise values and plot a histogram for each, with the cutoff determined by your binwidth.
Here is the approach. Note your data needed reformatting.
# reformat data
set.seed(1)
df <- data.frame(runif(1000, 0, 200))
colnames(df) <- "Time_Diff"
bp_overall <- ggplot(data = df)
bp_overall +
geom_histogram(data = subset(df, Time_Diff <= 12.5), aes(x = Time_Diff, fill="BAR BLUE"), binwidth = 5) + # subset for blue data, where aes fill is fill group 1 label
geom_histogram(data = subset(df, Time_Diff > 12.5), aes(x = Time_Diff, fill="BAR TURQUOISE"), binwidth = 5) + # subset for turquoise data, where aes fill is fill group 2 label
scale_fill_manual("Histogram Legend", values=c("blue", "paleturquoise2")) + # manually assign histogram fill colors
geom_vline(aes(xintercept = 3, colour="LINE DARK BLUE"), linetype="twodash", size = 1) + # where aes colour is vline label
scale_colour_manual("Line Legend", values="darkblue") + # manually assign vline colors
scale_x_continuous(breaks = seq(0, 202, 10)) +
ggtitle("Time Difference") +
xlab("Time in Days") +
ylab("Amount") +
theme_light() +
theme(panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"),
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black"))
Etc. add your remaining theme.
EDITED: To answer question on how to unify legend and decrease spacing between the two legend types
(1) Remove legend name for vline by setting to "" in scale_fill_manual, change histogram fill legend name to "Legend" in scale_colour_manual.
(2) Specify order in which legends should appear, fill first then colour using guides guide_legend.
(3) Remove the y-spacing between the two legend types by setting legend.spacing.y to 0, and remove margins on top and bottom using legend.margin in theme
bp_overall <- ggplot(data = df)
bp_overall +
geom_histogram(data = subset(df, Time_Diff <= 12.5), aes(x = Time_Diff, fill="BAR BLUE"), binwidth = 5) +
geom_histogram(data = subset(df, Time_Diff > 12.5), aes(x = Time_Diff, fill="BAR TURQUOISE"), binwidth = 5) +
scale_fill_manual(name="Legend", values=c("blue", "paleturquoise2")) +
geom_vline(aes(xintercept = 3, colour="LINE DARK BLUE"), linetype="twodash", size = 1) +
scale_colour_manual(name="", values="darkblue") +
scale_x_continuous(breaks = seq(0, 202, 10)) +
ggtitle("Time Difference") +
xlab("Time in Days") +
ylab("Amount") +
theme_light() +
theme(panel.grid.minor = element_blank(),
panel.border = element_blank(),
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"),
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black"),
legend.spacing.y = unit(0, "cm"),
legend.margin=margin(t=0, r=0.5, b=0, l=0.5, unit="cm")) +
guides(fill = guide_legend(order = 1),
colour = guide_legend(order = 2))

Resources