Move axis title towards plot and keep combmatrix labels - r

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.

Related

Color legends based on custom-fill colors using ggforce::geom_mark_ellipse()

I am trying to use custom colors for my plot and legends. However, when I run the code below, the legends disappear (see Fig. 1). The legends are present when I do not use custom colors to fill the ellipses (see Fig. 2). I will appreciate any suggestions.
Fig. 1:
Fig. 2:
library(palmerpenguins)
library(tidyverse)
library(ggplot2)
library(ggforce)
penguins <- penguins %>%
drop_na()
penguins %>% head() %>% print()
cols <- c("#0066cc","#9933ff","#66cc33")
my_color <- rep("", nrow(penguins))
cidx <- 0
for (color in unique(penguins$species)){
cidx <- cidx + 1
idx <- which(penguins$species == color)
my_color[idx] <- cols[cidx]
}
p <- penguins %>%
ggplot(aes(x = bill_length_mm,
y = flipper_length_mm))+
geom_mark_ellipse(aes(fill = I(my_color), alpha = I(0.2)),
# geom_mark_ellipse(aes(fill = species),
expand = unit(0.5,"mm"),
size = 0) +
geom_point(color = I(my_color))
plot(p)
You could achieve your requirements within the ggplot build-up using scales...
library(palmerpenguins)
library(ggplot2)
library(ggforce)
library(tidyr)
penguins <-
penguins |>
drop_na()
cols <- c("#0066cc","#9933ff","#66cc33")
penguins |>
ggplot(aes(x = bill_length_mm,
y = flipper_length_mm))+
geom_mark_ellipse(aes(fill = species),
colour = NA,
alpha = 0.2,
expand = unit(0.5,"mm"),
size = 0) +
geom_point(aes(color = species))+
scale_fill_manual(breaks = unique(penguins$species),
values = cols)+
scale_colour_manual(breaks = unique(penguins$species),
values = cols)
Created on 2022-10-21 with reprex v2.0.2
You could shorten the code substantially by using after_scale
library(palmerpenguins)
library(ggforce)
#> Loading required package: ggplot2
ggplot(tidyr::drop_na(penguins),
aes(bill_length_mm, flipper_length_mm, color = species)) +
geom_point() +
geom_mark_ellipse(aes(fill = after_scale(alpha(colour, 0.2))),
expand = unit(0.5, "mm"), size = 0) +
scale_colour_manual(values = c("#0066cc","#66cc33","#9933ff"))
Created on 2022-10-21 with reprex v2.0.2

Placing data labels for stacked bar chart at top of bar

I have been attempting to add a label on top of each bar to represent the proportion that each ethnic group makes up in referrals.
For some reason I cannot get the labels to be placed at the top of each bar. How do I fix this?
My code below
freq <- df %>%
group_by(ethnicity) %>%
summarise(n = n()) %>%
mutate(f = round((n/sum(n)*100, 1))
df %>%
group_by(pathway) %>%
count(ethnicity) %>%
ggplot(aes(x = ethnicity, y = n , fill = pathway)) +
geom_bar(stat = "identity", position = "stack") +
geom_text(data = freq,
aes(x= ethnicity, y = f, label = f),
inherit.aes = FALSE) +
theme(legend.position = "bottom") +
scale_fill_manual(name = "",
values = c("light blue", "deepskyblue4"),
labels = "a", "b") +
xlab("") +
ylab("Number of Referrals") +
scale_y_continuous(breaks = seq(0, 2250, 250), expand = c(0,0)
Here is what it currently looks like
Since you are using the count as your y-axis position in geom_bar, you need to use the same thing in your geom_text to get the labels in the right place. Below is an example using mtcars dataset. Using vjust = -1 I put a little bit of space between the label and the bars to make it more legible and aesthetically pleasing.
library(tidyverse)
mtcars %>%
group_by(carb) %>%
summarise(n = n()) %>%
mutate(f = round(proportions(n) * 100, 1)) -> frq
mtcars %>%
group_by(gear) %>%
count(carb) -> df
df %>%
ggplot(aes(x = carb, y = n, fill = gear)) +
geom_bar(stat = "identity", position = "stack") +
geom_text(data = frq,
vjust = -1,
aes(x= carb, y = n, label = f),
inherit.aes = FALSE)
Created on 2022-10-31 by the reprex package (v2.0.1)

How to automatically choose a good ylim to read geom_labels in ggplot2 in R

Suppose I write the following code with the diamonds dataset:
library(tidyverse)
diamonds %>%
group_by(cut) %>%
summarize(total_value = sum(price, na.rm = TRUE)) %>%
arrange(total_value) %>%
mutate(cut = as_factor(cut)) %>%
mutate(across(where(is.numeric), ~round(., 1))) %>%
ggplot(aes(x = cut, y = total_value)) +
geom_col(aes(fill = cut)) +
theme(legend.position = "note") +
coord_flip() +
geom_label(aes(label = paste0("$", total_value)), size = 6) +
labs(title = "Total Value of Diamonds by Cut", y = "USD", x = "") +
theme(axis.text = element_text(size = rel(1)))
which outputs the following plot:
As you can see, it is impossible to read the last digit(s) of the first category ("Ideal").
So, my question is, I know I can simply write something like coord_flip(ylim = c(0,80000000) and this would solve the problem; however, what could I write instead for ggplot2 to automatically know by itself how much space it should provide in ylim for people to clearly read the geom_label()s without me having to do this manually?
I'm trying to create an automatic Dashboard with multiple plots such as this, but I cannot manually tune every one of those, I need an automatic mechanism and I haven't found anything regarding this on StackOverflow for geom_label() specifically.
Thanks.
Instead of positioning your label at the the bar, you could move it closer to the middle and adjust position with vjust so it won't spill out of the plot set to include the bars.
library(tidyverse)
diamonds %>%
group_by(cut) %>%
summarize(total_value = sum(price, na.rm = TRUE)) %>%
arrange(total_value) %>%
mutate(cut = as_factor(cut)) %>%
mutate(across(where(is.numeric), ~round(., 1))) %>%
ggplot(aes(x = cut, y = total_value)) +
geom_col(aes(fill = cut)) +
theme(legend.position = "note") +
coord_flip() +
geom_label(aes(label = paste0("$", total_value), y = total_value/2), size = 6, hjust = 0.2) +
labs(title = "Total Value of Diamonds by Cut", y = "USD", x = "") +
theme(axis.text = element_text(size = rel(1)))
That gives:

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())

Rotate switched facet labels in ggplot2 facet_grid

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).

Resources