I want to plot four independent (in 2 rows and 2 columns) plots, each with a different flipped x axis. I have used ggplot with a face_wrap but this approach doesn't give each plot its own flipped x-axis labels.
Is there a way to achieve my goal in ggplot2?
library(tidyverse)
data <- read_csv('https://raw.githubusercontent.com/rnorouzian/e/master/surv.csv')
names(data)[2:5] <- c("Representation", "Solidification", "Application", "Confidence")
data %>%
pivot_longer(cols = -id) %>%
mutate(name = name,
value = str_wrap(value, 50)) %>%
ggplot() +
geom_bar(aes(value, fill = name), show.legend = FALSE) +
facet_wrap(.~name) +
coord_flip() +
labs(y = "Students", x = "") +
theme(axis.text.y = element_text(size=8))
Adding scales = 'free_y' to your original code.
Edit: add code to manually change order of the levels.
level_order <- c("Neutral",
"Agree",
"Strongly Agree",
"The assignment gave me a great opportunity to\napply what I learned",
"The assignment gave me an opportunity to apply\nwhat I learned",
"The assignment helped me solidify the key concepts",
"The assignment highly helped me solidify the key\nconcepts",
"The assignment highly reflected the class\ninstructions",
"The assignment reflected the class instructions",
"The assignment somewhat reflected the class\ninstructions")
data %>%
pivot_longer(cols = -id) %>%
mutate(name = name,
value = str_wrap(value, 50),
value = factor(value, levels = level_order)) %>%
ggplot() +
geom_bar(aes(value, fill = name), show.legend = FALSE) +
facet_wrap(.~name, scales = 'free_y') +
coord_flip() +
labs(y = "Students", x = "") +
theme(axis.text.y = element_text(size=8))
I would suggest next approach:
#Code
library(tidyverse)
data <- read_csv('https://raw.githubusercontent.com/rnorouzian/e/master/surv.csv')
names(data)[2:5] <- c("Representation", "Solidification", "Application", "Confidence")
The option 1 would be adjusting facet_wrap():
#Option 1
data %>%
pivot_longer(cols = -id) %>%
mutate(name = name,
value = str_wrap(value, 50)) %>%
ggplot() +
geom_bar(aes(value, fill = name), show.legend = FALSE) +
facet_wrap(.~name,scales='free') +
labs(y = "Students", x = "") +
theme(axis.text.y = element_text(size=8))
And the second option would be create a list and a function for the plots:
#Option 2
data2 <- data %>%
pivot_longer(cols = -id) %>%
mutate(name = name,
value = str_wrap(value, 50))
#Split
LData2 <- split(data2,data2$name)
#Now function to plot
myfun <- function(x)
{
mplot <- ggplot(x,aes(value, fill = name)) +
geom_bar(show.legend = FALSE) +
labs(y = "Students", x = "") +
theme(axis.text.y = element_text(size=8))+
ggtitle(unique(x$name))
return(mplot)
}
#Apply
Lplots <- lapply(LData2,myfun)
Some example output:
#Example
Lplots[[1]]
Or using patchwork with wrap_plots() in the list:
library(patchwork)
#Code
wrap_plots(Lplots)
Output:
Or changing the axis orientation and using patchwork:
#Now function to plot 2
myfun <- function(x)
{
mplot <- ggplot(x,aes(value, fill = name)) +
geom_bar(show.legend = FALSE) +
labs(y = "Students", x = "") +
coord_flip()+
theme(axis.text.y = element_text(size=8))+
ggtitle(unique(x$name))
return(mplot)
}
#Apply
Lplots <- lapply(LData2,myfun)
#Wrap
wrap_plots(Lplots)
Output:
Related
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 can I make a graphic bar using barplot() or ggplopt() of an excel archive that has 83 columns?
I need to plot every column that has a >0 value on ich raw. (ich column represents a gene function and I need to know how many functions there is on ich cluster).
Iwas trying this,but it didn't work:
ggplot(x, aes(x=Cluster, y=value, fill=variable)) +
geom_bar(stat="bin", position="dodge") +
theme_bw() +
ylab("Funções no cluster") +
xlab("Cluster") +
scale_fill_brewer(palette="Blues")
Link to the excel:
https://github.com/annabmarques/GenesCorazon/blob/master/AllclusPathwayEDIT.xlsx
What about a heatmap? A rough example:
library(dplyr)
library(tidyr)
library(ggplot2)
library(openxlsx)
data <- read.xlsx("AllclusPathwayEDIT.xlsx")
data <- data %>%
mutate(cluster_nr = row_number()) %>%
pivot_longer(cols = -c(Cluster, cluster_nr),
names_to = "observations",
values_to = "value") %>%
mutate(value = as.factor(value))
ggplot(data, aes(x = cluster_nr, y = observations, fill = value)) +
geom_tile() +
scale_fill_brewer(palette = "Blues")
Given the large number of observations consider breaking this up into multiple charts.
It's difficult to understand exactly what you're trying to do. Is this what you're trying to achieve?
#install.packages("readxl")
library(tidyverse)
library(readxl)
read_excel("AllclusPathwayEDIT.xlsx") %>%
pivot_longer(!Cluster, names_to = "gene_counts", values_to = "count") %>%
mutate(Cluster = as.factor(Cluster)) %>%
ggplot(aes(x = Cluster, y = count, fill = gene_counts)) +
geom_bar(position="stack", stat = "identity") +
theme(legend.position = "right",
legend.key.size = unit(0.4,"line"),
legend.text = element_text(size = 7),
legend.title = element_blank()) +
guides(fill = guide_legend(ncol = 1))
ggsave(filename = "example.pdf", height = 20, width = 35, units = "cm")
my data looks like
Fem_Applied <- c(10,15,10)
Fem_Success <- c(3,5,2)
Mal_Applied <- c(20,15,20)
Mal_Success <- c(4,3,3)
Role <- c("A","B","C")
df <- data.frame(Role,Fem_Applied,Fem_Success,Mal_Applied,Mal_Success)
And while I can plot it ok useing melt(df) and role as ID variables by default, I end up with 4 columns. What I want is two columns, one red for women and one blue for men. And the applied stacked on top of the successfull with applied alpha being lower
It sounds like you're looking for something like this:
library(tidyr)
library(reshape2)
library(ggplot2)
library(dplyr)
separate(melt(df), "variable", into = c("Gender", "Result"), sep = "_") %>%
mutate(fillcat = paste(Gender, Result)) %>%
ggplot(aes(Gender, value, fill = fillcat)) +
geom_col(aes(group = Result)) +
scale_fill_manual(values = c("#FF3456", "#FF345680", "#3456FF", "#3456FF80")) +
facet_grid(~Role, switch = "x") +
labs(x = "Role", y = "Count") +
theme_classic() +
theme(panel.spacing = unit(0, "points"),
legend.position = "none",
strip.placement = "outside",
strip.background = element_blank())
You can use something like the following
library(tidyverse)
df %>%
pivot_longer(cols = -Role) %>%
separate(name, c("Gender", "b"), convert = T) %>%
ggplot(aes(x = Gender, y = value, fill = b)) +
geom_col()
To have role wise plot you can use
df %>%
pivot_longer(cols = -Role) %>%
separate(name, c("Gender", "b"), convert = T) %>%
ggplot(aes(x = Gender, y = value, fill = b)) +
geom_col() + facet_wrap(Role~.)
I am trying to make part of my title in italics (M.alfredi) but cant figure out how? Can anyone help? Thanks.
library(tidyverse)
library(reshape2)
dat <- read_xlsx("ReefPA.xlsx")
names(dat) <- str_replace_all(names(dat), " ", "_")
dat1 <- dat d
at1$Date <- format(dat1$Date, "%Y/%m")
dat1 %>%
group_by(Date) %>%
tally() %>%
filter(Date > '2014-01-01') %>%
ggplot() +
geom_bar(aes(x = Date, y = n), stat = 'identity') +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)) +
ylab("Total Number of M.alfredi Encounters Per Month")
You can use plotmath expressions to label your axis. There is no sample data here, but this mock-up should suffice:
ggplot(data = data.frame(x = 1:30, y = round(runif(30, 20, 50))), aes(x, y)) +
geom_col() +
labs(y = expression("Total Number of "~italic(M.alfredi)~"Encounters Per Month"))
I am trying to create faceted geom_bar graphs with the following charactaristics:
The proportion of each answer per question is shown
Each bar is colored according to the response
The plot is faceted by question
I seem to be able to do any two of the conditions, but not all 3.
Question:
Is there a way to facet and calculate proportions using one variable, but colour/fill based on another variable?
Code:
df <- data.frame(
Question = rep(c('A', 'B', 'C'), each = 5),
Resp = sample(c('Yes', 'No', 'Unsure', NA), 15, T, c(0.3,0.3,0.3,0.1)),
stringsAsFactors = F
)
# Plot 1: grouping by question to get the right proportions, but has no colour
ggplot(df, aes(x = Resp, fill = Resp)) +
stat_count(aes(y = ..prop.., group = Question)) +
scale_y_continuous(labels = scales::percent_format()) +
facet_wrap(~ Question)
# Plot 2: grouping by response to get colour, but has wrong proportions
ggplot(df, aes(x = Resp, fill = Resp)) +
stat_count(aes(y = ..prop.., group = Resp)) +
scale_y_continuous(labels = scales::percent_format()) +
facet_wrap(~ Question)
Outputs:
This is a "ggplot2-only" option:
ggplot(df, aes(x = Resp)) +
geom_bar(aes(y = ..prop.., group = Question, fill = factor(..x..)), position = "dodge") +
scale_y_continuous(labels = scales::percent_format()) +
scale_fill_discrete(name = "Response", labels = c("No", "Unsure", "Yes", "NA")) +
facet_wrap(~ Question)
One way could be to calculate the proportions and then plot.
library(dplyr)
library(ggplot2)
df %>%
count(Question, Resp) %>%
group_by(Question) %>%
mutate(n = n/sum(n) * 100) %>%
ggplot() + aes(Resp, n, fill = Resp) +
geom_col() +
facet_wrap(~Question)
Plot without facet
df$n <- 1
df <- df %>% group_by(Question, Resp) %>% summarise(n = sum(n))
ggplot(df, aes(x=factor(Question), y=n, fill=Resp)) + geom_col()
Plot with facet
df <- df %>% group_by(Question, Resp) %>% summarise(n = sum(n)) %>% mutate(prop = n/5)
ggplot(df, aes(x=factor(Resp), y=prop, fill=Resp)) + geom_col() + facet_wrap(~Question)