Rotate switched facet labels in ggplot2 facet_grid - r

I would like to plot some barplots on top of each other using facet_grid:
library(ggplot2)
df <- group_by(mpg, manufacturer) %>%
summarise(cty = mean(cty), hwy = mean(hwy)) %>%
ungroup()
df <- melt(df, id.vars = "manufacturer")
ggplot() +
geom_bar(data =df, aes(x = variable, y = value), stat = "identity") +
facet_grid(manufacturer ~ ., switch = "y")
I use the switchargument of ggplot2::facet_grid()to let the facet labels be displayed on the y-axis instead of on top of each facet. Problem is that the facet labels are plotted vertically and therefore cropped. Is there any way to plot the facet -labels horizontally? All the questions I found so far related to rotating the x-axis labels only, not the facet labels.

You just need to add the theme() and specify the angle in strip.text.y.left.
library(tidyverse)
library(reshape2)
df <- group_by(mpg, manufacturer) %>%
summarise(cty = mean(cty), hwy = mean(hwy)) %>%
ungroup()
df <- melt(df, id.vars = "manufacturer")
ggplot() +
geom_bar(data =df, aes(x = variable, y = value), stat = "identity") +
facet_grid(manufacturer ~ ., switch = "y")+
theme(strip.text.y.left = element_text(angle = 0))
Created on 2020-03-15 by the reprex package (v0.3.0)
Note that strip.text.y.left was added in ggplot2 3.3.0. For earlier versions, you need to write strip.text.y = element_text(angle = 180).

Related

Move axis title towards plot and keep combmatrix labels

I am trying to move the y axis title towards the ticks. However, I'm having trouble doing this without cutting off the combmatrix labels. I've tried both with ggupset and ggplot functions. See reprex below.
Thank you for your help!
library(dplyr)
library(ggupset)
library(ggplot2)
tidy_pathway_member <-
gene_pathway_membership %>%
as_tibble(rownames = "Pathway") %>%
tidyr::gather(Gene, Member, -Pathway) %>%
filter(Member) %>%
select(- Member)
g <-
tidy_pathway_member %>%
group_by(Gene) %>%
summarize(Pathways = list(Pathway)) %>%
ggplot(aes(x = Pathways)) +
geom_bar() +
scale_x_upset()
g
g +
# Moves axis title towards ticks...but cuts off labels
theme_combmatrix(combmatrix.label.make_space = FALSE)
g +
# Also, moves axis title towards ticks...but cuts off labels
theme(axis.title.y = element_text(margin = margin(r = -100)))
Created on 2021-07-30 by the reprex package (v2.0.0)
Like this?
library(dplyr)
library(ggupset)
library(ggplot2)
tidy_pathway_member <-
gene_pathway_membership %>%
as_tibble(rownames = "Pathway") %>%
tidyr::gather(Gene, Member, -Pathway) %>%
filter(Member) %>%
select(- Member)
g <-
tidy_pathway_member %>%
group_by(Gene) %>%
summarize(Pathways = list(Pathway)) %>%
ggplot(aes(x = Pathways)) +
geom_bar() +
scale_x_upset() +
# the exact vjust number needed may vary depending on the plotting area size
theme(axis.title.y = element_text(vjust=-30))
g
BTW the same solution should work for ComplexUpset in principle.
This can be done in a tricky way.
The solution is to hide the y axis title and add text with annotate() to the target position.
Since you did not provide your data, I will show it on an example.
Original plot:
ggplot(data = diamonds, mapping = aes(x = clarity)) + geom_bar(aes(fill = cut))
Version with annotate in place of the y-axis title:
ggplot(data = diamonds, mapping = aes(x = clarity)) + geom_bar(aes(fill = cut)) +
theme(axis.title.y=element_blank()) + annotate(geom = "text", x = -0.2, y = 6500, label = "count", angle = 90, size=4) +
coord_cartesian(xlim = c(1, 8), clip = "off")
You just need to set the appropriate x and y coordinates and xlim inside coord_cartesian.

How to make a barplot of percentages in ggplot2

I have a set of data as such;
Station;Species;
CamA;SpeciesA
CamA;SpeciesB
CamB;SpeciesA
etc...
I would like to create a cumulative barplot with the cameras station in x axis and the percentage of each species added. I have tried the following code;
ggplot(data=data, aes(x=Station, y=Species, fill = Species))+ geom_col(position="stack") + theme(axis.text.x =element_text(angle=90)) + labs (x="Cameras", y= NULL, fill ="Species")
And end up with the following graph;
But clearly I don't have a percentage on the y axis, just the species name - which is in the end what I have coded for..
How could I have the percentages on the y axis, the cameras on the x axis and the species as a fill?
Thanks !
Using mtcars as example dataset one approach to get a barplot of percentages is to use geom_bar with position = "fill".
library(ggplot2)
library(dplyr)
mtcars2 <- mtcars
mtcars2$cyl = factor(mtcars2$cyl)
mtcars2$gear = factor(mtcars2$gear)
# Use geom_bar with position = "fill"
ggplot(data = mtcars2, aes(x = cyl, fill = gear)) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent_format()) +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Cameras", y = NULL, fill = "Species")
A second approach would be to manually pre-compute the percentages and make use of geom_col with position="stack".
# Pre-compute pecentages
mtcars2_sum <- mtcars2 %>%
count(cyl, gear) %>%
group_by(cyl) %>%
mutate(pct = n / sum(n))
ggplot(data = mtcars2_sum, aes(x = cyl, y = pct, fill = gear)) +
geom_col(position = "stack") +
scale_y_continuous(labels = scales::percent_format()) +
theme(axis.text.x = element_text(angle = 90)) +
labs(x = "Cameras", y = NULL, fill = "Species")

How to create scaled and faceted clustered bargraphs of a summarized dataframe in ggplot2?

I am trying to create a grid of bargraphs that show the average for different species. I am using the iris dataset for this question.
I summarised the data, melted it into long form long, and tried to use facet_wrap.
iris %>%
group_by(Species) %>%
summarise(M.Sepal.Length=mean(Sepal.Length),
M.Sepal.Width=mean(Sepal.Width),
M.Petal.Length= mean(Petal.Length),
M.Petal.Width=mean(Petal.Width)) %>%
gather(key = Part, value = Value, M.Sepal.Length:M.Petal.Width) %>%
ggplot(., aes(Part, Value, group = Species, fill=Species)) +
geom_col(position = "dodge") +
facet_grid(cols=vars(Part)) +
facet_grid(cols = vars(Part))
However, the graph I am getting has x.axis labels that are strung across each facet grid. Additionally the clustered graphs are not centered within each facet box. Instead they appear at the location of their respective x-axis label. I'd like to get rid of the x-axis labels, center the graphs, and scale the graphs within each facet.
Here is an image of the resulting graph marked up with my expected output:
Perhaps this is what you're looking for?
The key changes are:
Remove Part as the variable mapped to x, that way the data is plotted in the same location in every facet
Switch to facet_wrap so you can use scales = "free_y"
Use labs to manually add the x title
Add theme to get rid of the x-axis ticks and tick labels.
library(ggplot2)
library(dplyr) # Version >= 1.0.0
iris %>%
group_by(Species) %>%
summarise(across(1:4, mean, .names = "M.{col}")) %>%
gather(key = Part, value = Value, M.Sepal.Length:M.Petal.Width) %>%
ggplot(., aes(x = 1, y = Value, group = Species, fill=Species)) +
geom_col(position = "dodge") +
facet_wrap(.~Part, nrow = 1, scales = "free_y") +
labs(x = "Part") +
theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank())
I also took the liberty of switching out your manual call to summarise with the new across functionality.
Here's how you might also calculate error bars:
library(tidyr)
iris %>%
group_by(Species) %>%
summarise(across(1:4, list(M = mean, SE = ~ sd(.)/sqrt(length(.))),
.names = "{fn}_{col}")) %>%
pivot_longer(-Species, names_to = c(".value","Part"),
names_pattern = "([SEM]+)_(.+)") %>%
ggplot(., aes(x = 1, y = M, group = Species, fill=Species)) +
geom_col(position = "dodge") +
geom_errorbar(aes(ymin = M - SE, ymax = M + SE), width = 0.5,
position = position_dodge(0.9)) +
facet_wrap(.~Part, nrow = 1, scales = "free_y") +
labs(x = "Part", y = "Value") +
theme(axis.ticks.x = element_blank(),
axis.text.x = element_blank())

The labels are below the bars in the R barplot

I was trying to put the labels to all the bars on the plot, but some of them keep being under the bars. What should I edit in the code?
ggplot(data, aes(x = year,y = value)) +
geom_text(aes(label=value), vjust=-3.5, size=3.5)+
geom_bar(aes(fill = variable), stat = "identity",position = "dodge")+
scale_x_continuous(breaks = unique(data$year))+
ylab("Number of candidates")+
theme(axis.title.x=element_blank())+
scale_fill_discrete(name="",
labels=c("All", "Female"))
You need to add position_dodge to your geom_text in order to follow the position_dodge of the geom_bar.
Here, I took the example of the iris dataset that I reshape using pivot_longer
library(tidyverse)
ir_df <- iris %>% group_by(Species) %>%
summarise(Mean_Length = mean(Sepal.Length), Mean_Width = mean(Sepal.Width)) %>%
pivot_longer(., -Species, names_to = "Variables", values_to = "Value")
library(ggplot2)
ggplot(ir_df, aes(x = Species, y = Value, fill = Variables))+
geom_bar(stat = "identity", position = position_dodge()) +
geom_text(aes(label = Value), vjust = -3.5, position = position_dodge(width = 1))
If you don't succeed to adapt this code to your dataset, please consider to provide a reproducible example of your dataset

ggplot2: plot correct proportions using geom_bar

I am trying to plot proportion of diamonds using geom_bar and position = "dodge". Here is what I have done.
library(ggplot2)
ggplot(data = diamonds) + geom_bar(mapping = aes(x = cut))
The image below tell me how many diamonds are there for each cut type.
Now let's do something fancy.
ggplot(data = diamonds) + geom_bar(mapping = aes(x = cut, fill = clarity), position = "dodge")
The image below provides count of by grouping diamonds by clarity for each cut type.
What I would like to do is get the same dodge plot as above but showing proportion instead of count.
For example, for cut=ideal and clarity = VS2, the proportion should be 5071/21551 = 0.23.
You can try
library(tidyverse)
diamonds %>%
count(cut, clarity) %>%
group_by(cut) %>%
mutate(Sum=sum(n)) %>%
mutate(proportion = n/Sum) %>%
ggplot(aes(y=proportion, x=cut,fill=clarity)) +
geom_col(position = "dodge")
create a column with the correct percentages (named "percentage"), and use
require(ggplot2)
require(scales)
ggplot(data = diamonds) +
geom_bar(mapping = aes(x = cut, y = percentage, fill = clarity), position = "dodge") +
scale_y_continuous(labels = scales::percent)
You can also calculate the percentage inline, as Maurits Evers suggests.

Resources