facet grid to split the ggplot bar plot by group - r

I want to draw a bar plot using ggplot, with reorder the variables based on each group and split the gg bar plot by the groups. Here a samples example.
M <- data.frame(group = c(rep("A", 3), rep("B",4), rep("C", 2)), values = runif(9,-3,4), names = paste0("G", seq(1,9)))
ggplot(M) +
theme_minimal() +
aes(x = reorder(names,values), y = values, fill = factor(sign(values))) +
geom_bar(stat="identity", width = 0.5, show.legend = T, alpha = 0.75, position=position_dodge()) +
scale_fill_manual(values=c('mediumorchid4', 'goldenrod')) +
ggtitle("") +
theme(axis.text.y = element_text(size = "12", face = "bold"),
plot.title = element_text(face = "bold" , size = 10)) +
xlab("Names") +
ylab("Values") +
geom_hline(yintercept = 0, size = 1, color = "black") +
coord_flip()
For this example, I want to reorder the samples based on each group, then split horizontally by the groups, and the bar colors adjust by the sign of the values to different colors. Thank you.

It sounds like you are looking for something like this:
ggplot(M) +
theme_minimal() +
aes(x = reorder(names, values), y = values, fill = factor(sign(values))) +
geom_bar(stat="identity", width = 0.5, show.legend = TRUE, alpha = 0.75,
position=position_dodge()) +
scale_fill_manual(values=c('mediumorchid4', 'goldenrod')) +
ggtitle("") +
theme(axis.text.y = element_text(size = "12", face = "bold"),
plot.title = element_text(face = "bold" , size = 10)) +
xlab("Names") +
ylab("Values") +
geom_hline(yintercept = 0, size = 1, color = "black") +
coord_flip() +
facet_grid(group~., space = "free_y", scales = "free_y", drop = TRUE)

Related

Creating ggplot geom_point() with position dodge 's-shape'

I am trying to create a plot like the one below. I'd like the order the points in each category in such a way that they form an s-shape. Is it possible to do this in ggplot?
Similar data available here
What I have so far:
somatic.variants <- read.delim("data/Lawrence.S2.txt", stringsAsFactors=T)
cancer_rates <- tapply(somatic.variants$logn_coding_mutations, somatic.variants$tumor_type, median)
cancer_rates <- cancer_rates[order(cancer_rates, decreasing=F)]
somatic.variants$tumor_type <- factor(somatic.variants$tumor_type, levels = names(cancer_rates))
library(ggplot2)
library(GGally)
ggplot(data = somatic.variants,
mapping = aes(x = tumor_type,
y = log10(n_coding_mutations))) +
geom_point(position = position_dodge2()) +
scale_x_discrete(position = "top") +
scale_y_continuous(labels = c(0,10,100,1000,10000), expand = c(0,0)) +
geom_stripped_cols() +
theme_bw() +
theme(axis.title.x = element_blank(),
axis.text.x = element_text(angle = 315, hjust = 1, size = 12),
panel.grid = element_blank()) +
labs(y = "Coding mutations count") +
stat_summary(fun = median,
geom="crossbar",
size = 0.25,
width = 0.9,
group = 1,
show.legend = FALSE,
color = "#FF0000")
This could be achieved by
grouping the data by x-axis categories
arranging by the y-axis value
which ensures that the points are plotted in ascending order of the values for each category.
somatic.variants <- read.delim("https://gist.githubusercontent.com/wudustan/57deecdaefa035c1ecabf930afde295a/raw/1594d51a1e3b52f674ff746caace3231fd31910a/Lawrence.S2.txt", stringsAsFactors=T)
cancer_rates <- tapply(somatic.variants$logn_coding_mutations, somatic.variants$tumor_type, median)
cancer_rates <- cancer_rates[order(cancer_rates, decreasing=F)]
somatic.variants$tumor_type <- factor(somatic.variants$tumor_type, levels = names(cancer_rates))
library(ggplot2)
library(GGally)
library(dplyr)
somatic.variants <- somatic.variants %>%
group_by(tumor_type) %>%
arrange(n_coding_mutations)
ggplot(data = somatic.variants,
mapping = aes(x = tumor_type,
y = log10(n_coding_mutations))) +
geom_point(position = position_dodge2(.9), size = .25) +
scale_x_discrete(position = "top") +
scale_y_continuous(labels = c(0,10,100,1000,10000), expand = c(0,0)) +
geom_stripped_cols() +
theme_bw() +
theme(axis.title.x = element_blank(),
axis.text.x = element_text(angle = 315, hjust = 1, size = 12),
panel.grid = element_blank()) +
labs(y = "Coding mutations count") +
stat_summary(fun = median,
geom="crossbar",
size = 0.25,
width = 0.9,
group = 1,
show.legend = FALSE,
color = "#FF0000")
#> Warning: Removed 29 rows containing non-finite values (stat_summary).

Setting all theme elements blank does not affect the axis elemenets

I have the dataframe below
GO<-c("cytosol (GO:0005829)","cytosol (GO:0005829)")
FE<-c(2.70,4.38)
FDR<-c(0.00159,0.00857)
Facet<-c("ileum 24h","ileum 72h")
CCC<-data.frame(GO,FE,FDR,Facet)
and with this code
CCC %>%
arrange(desc(CCC$GO))%>%
ggplot(aes(x = FDR, y = GO, size = FE, color = FDR)) +
geom_point(alpha = 0.5) +
scale_size(range = c(5, 8), name = "Fold enrichment") +
facet_grid(cols = vars(Facet), scales = "free") +
theme(axis.title.x=element_blank(),axis.text.x = element_text(angle = 45, vjust = 0.5, hjust = 1)) +
scale_y_discrete(name = "GO biological process complete") +
scale_x_continuous(name = "FDR") +
scale_colour_gradient(low = "yellow", high = "red", name = "FDR") +
theme_bw()
I create a bubble plot with facets. But I want to delete the x-axis title 'FDR' and display the labels with an angle but despite setting the theme() it does not change.
You have put theme_bw() at the end, which over-writes your theme call. Put your custom themes at the end:
CCC %>%
arrange(desc(CCC$GO))%>%
ggplot(aes(x = FDR, y = GO, size = FE, color = FDR)) +
geom_point(alpha = 0.5) +
scale_size(range = c(5, 8), name = "Fold enrichment") +
scale_y_discrete(name = "GO biological process complete") +
scale_x_continuous(name = "FDR") +
scale_colour_gradient(low = "yellow", high = "red", name = "FDR") +
facet_grid(cols = vars(Facet), scales = "free") +
theme_bw() +
theme(axis.title.x = element_blank(),
axis.text.x = element_text(angle = 45, vjust = 0.5, hjust = 1))
I think it is good practice to lay out your calls to ggplot in a consistent way so that this kind of thing doesn't happen:
Call ggplot +
Geom (and stat) layers, ordered depending on which ones you want on top +
Scales +
Facets +
Labels and titles +
Global themes like theme_bw() +
Individual theme tweaks via theme
Only change the position of theme_bw():
library(tidyverse)
#Data
GO<-c("cytosol (GO:0005829)","cytosol (GO:0005829)")
FE<-c(2.70,4.38)
FDR<-c(0.00159,0.00857)
Facet<-c("ileum 24h","ileum 72h")
CCC<-data.frame(GO,FE,FDR,Facet)
#Plot
CCC %>%
arrange(desc(CCC$GO))%>%
ggplot(aes(x = FDR, y = GO, size = FE, color = FDR)) +
geom_point(alpha = 0.5) +
scale_size(range = c(5, 8), name = "Fold enrichment") +
facet_grid(cols = vars(Facet), scales = "free") +
xlab('')+
theme_bw()+
theme(axis.title.x=element_blank(),
axis.text.x = element_text(angle = 45, vjust = 0.5, hjust = 1)) +
scale_y_discrete(name = "GO biological process complete") +
scale_x_continuous(name = "") +
scale_colour_gradient(low = "yellow", high = "red", name = "FDR")
Output:

How do I reverse the order in which error bars appear using geom_errorbar() in R?

I have the following example plot:
test <- data.frame("Factor" = as.factor(c("O", "C", "A")),
b = c(0.18, .34, .65, -.13, .38, .26),
lower95 = c(-.1, .09, .34, -.52, .10, -.02),
upper95 = c(.48, .58, .98, .26, .67, .56),
group = factor(c("Experiment 1","Experiment 2")))
test$Factor <- factor(test$Factor, as.character(test$Factor))
test$group <- factor(test$group, as.character(test$group))
ggplot(test, aes(Factor, b, colour = group)) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
)
As you'll see, the error bars appear in the reverse order (from top to bottom) as they do in the legend. I would like Experiment 1 error bars to appear above Experiment 2 error bars.
I have tried
ggplot(test, aes(Factor, b, colour = forcats::fct_rev(groups)
But this reverses the order of the group labels in the legend, not the order of the colours in the legend–which is what would work. I have also tried reversing the order in which I enter them in the data frame and this does not solve the problem.
I would appreciate some help!
Re-factoring will change the order of the plot, but, as you saw, also changes the order of the legend. In addition to reversing the levels of group, you can reverse the order the legend is displayed with the reverse argument in guide_legend.
ggplot(test, aes(Factor, b, colour = forcats::fct_rev(group))) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
) +
guides(color = guide_legend(reverse = TRUE) )
If you are using scale_color_discrete or scale_color_manual to control other scale elements like the legend name, you can use guide_legend there instead of via guides.
+
scale_color_discrete(name = "Experiment", guide = guide_legend(reverse = TRUE) )
Do you mean something like this?
test$Factor <- factor(test$Factor, levels = rev(levels(test$Factor)));
test$group <- factor(test$group, levels = rev(levels(test$group)));
ggplot(test, aes(Factor, b, colour = group)) +
geom_errorbar(aes(ymin = lower95, ymax = upper95),
size = 1,
width = .5,
position = 'dodge') +
geom_hline(yintercept = 0) +
ylim(-1.25, 1.25) +
coord_flip() +
theme_bw() +
ggtitle("Title") +
theme(
axis.text=element_text(size = 20),
axis.title=element_text(size = 18),
plot.title = element_text(size = 20, face = "bold"),
axis.text.y=element_text(size = 12)
)
I'm not entirely clear on whether you want to reverse the ordering of test$Factor as well; just (un)comment the corresponding line depending on what you're after.

ggplot pie chart choose axes ticks

I would like to know if it's possible to modify the ticks of x axis with a ggplot pie chart.
Here what I can do :
# Some colors
couleurs <- data.frame(
id=seq(1,17,1),
mix=c(c(rep(1,6),rep(2,7),rep(3,4))),
html=c("#A00020","#109618","#388EE4","#C484D1","#FFAA33","#CCCDD0","#004AC5","#F80094","#CB5023","#638995","#33CFCF","#95DC4E","#F7D633","#5C403C","#F72020","#00D96C","#FDE4C5")
)
couleurs$html <- factor(couleurs$html, levels = couleurs$html[order(couleurs$id, decreasing = FALSE)])
# Data
activite <- data.frame(label=c("B to B","B to C","B to B / B to C", "B to B"), cible=c(rep("Externe",3), "Interne"), nb=c(12,9,3,12))
activite$label <- factor(activite$label, levels = activite$label[order(activite$nb[activite$cible=="Externe"], decreasing = TRUE)])
library(plyr)
activite<-ddply(activite,.(cible),transform,pc=(nb/sum(nb))*100)
activite
# Pie chart
library(ggplot2)
ggplot(data = activite, aes(x = "", y = nb, fill = label )) +
geom_bar(stat = "identity", position = position_fill(), width = 1) +
coord_polar(theta= "y", start = 0, direction = -1) +
labs(fill="") +
scale_fill_manual(values=as.character(couleurs$html[1:nrow(activite)]), labels=paste(activite$label,"\t\t\t",sep="")) +
geom_text(aes(label = paste(pc,"%", sep=" ")), size=4, colour = "white", fontface = "bold", position = position_fill(vjust = 0.5)) +
theme(strip.text = element_text(size=20, face = "bold", ), strip.background = element_rect(fill="grey75")) +
theme(panel.background = element_rect(fill = "white")) +
theme(plot.background = element_rect(fill = "grey92")) +
theme(legend.position="bottom", legend.background = element_rect(fill="grey92")) +
theme(legend.key = element_blank()) +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_line(colour = "grey75")) +
theme(axis.text.y = element_blank()) +
theme(axis.ticks.length = unit(0, "mm")) +
theme(axis.title.x = element_blank(),axis.title.y = element_blank()) +
theme(legend.box.spacing = unit(1, "mm")) +
facet_wrap(~ cible)
Here my result:
After several hours of serach, I didn't find a solution to create what I want. The exact same pie chart but with personalised ticks like that :
With these particular conditions :
- do not change the direction of the data in the pie chart, I want it like exactly this
- if possible (but if not possible, it's okay), I would like the ticks' labels not superposed with the axis.
If someone can help me, I would really appreciate.
Here's one solution:
ggplot(data = activite %>%
group_by(cible) %>%
arrange(desc(nb)) %>%
mutate(axis.label = cumsum(nb),
axis.position = cumsum(pc)/100) %>%
mutate(axis.label = ifelse(pc == min(pc),
paste(axis.label, "0", sep = "-"),
axis.label)),
aes(x = 1, y = nb, fill = label )) +
geom_segment(aes(x = 1, xend = 1.6, y = axis.position, yend = axis.position),
colour = "grey75") +
geom_vline(xintercept = 1.6, colour = "grey75") +
geom_bar(stat = "identity", position = position_fill(reverse = T), width = 1) +
coord_polar(theta= "y", start = 0, direction = 1) +
labs(fill="") +
scale_fill_manual(values=as.character(couleurs$html[1:nrow(activite)]), labels=paste(activite$label,"\t\t\t",sep="")) +
geom_text(aes(label = paste(pc,"%", sep=" ")), size=4, colour = "white",
fontface = "bold", position = position_fill(vjust = 0.5, reverse = T)) +
geom_text(aes(x = 1.7, label = axis.label), size = 3,
position = position_fill(reverse = T)) +
theme(strip.text = element_text(size=20, face = "bold", ), strip.background = element_rect(fill="grey75")) +
theme(panel.background = element_rect(fill = "white")) +
theme(plot.background = element_rect(fill = "grey92")) +
theme(legend.position="bottom", legend.background = element_rect(fill="grey92")) +
theme(legend.key = element_blank()) +
theme(panel.grid = element_blank()) +
theme(axis.text = element_blank()) +
theme(axis.ticks = element_blank()) +
theme(axis.title = element_blank()) +
theme(legend.box.spacing = unit(1, "mm")) +
facet_wrap(~ cible)
Explanation:
The sequence in your labels went clockwise, while the direction of the polar coordinates went counter-clockwise. That makes labelling rather troublesome. I switched the direction for polar coordinates, & added reverse = T inside the position adjustment calls for the geoms.
It's hard to assign different axis breaks to different facets of the same plot, so I didn't. Instead, I modified the data to include calculated axis labels / margin positions, added margins via geom_segment / geom_vline, & hid the axis text / ticks in theme().

Define different label size by category in geom_bar

I am trying to plot a stacked barchart using geom_bar and label each category with its value within the barchart. Because some categories have small values, the height of the corresponding segment of the barchart is sometimes small. So, I am trying to adjust the size of the labels using geom_text.
I have tried to define a vector, called size, that varies according to the value of the variable I am trying to plot but,although the size of the labels does vary between categories, it does not seem to be related to the values. Also, I am not sure why I am getting a legend for my label size on the right-hand side of the graph.
Here is a stripped version of the code I am using:
library(ggplot2)
library(plyr)
library(scales)
Var1 = as.factor(rep(c("A", "B", "C", "D", "E", "F"),2))
Var2 = as.factor(rep(c("Y1","Y2"),each=6))
Freq = c(0.4, 0.1, 0.3, 0.1, 0.05, 0.05,0.2,0.2,0.3,0.2,0.05,0.05)
Data = data.frame(Var1, Var2, Freq)
Data <- ddply(Data, .(Var2), mutate, y = cumsum(Freq)-Freq/2)
size = ifelse(Data$Freq > 0.05, 10, 3)
label = paste(round(Data$Freq*100,0),"%", sep = "")
p = ggplot(data = Data, aes(x = factor(''), y = Freq, fill = Var1)) +
geom_bar(stat = "identity",position = "fill", width = 1) +
scale_fill_brewer(palette = 3) +
facet_grid(facets = . ~ Var2) +
geom_text(aes(y = y, label = label,
position ="identity", face = "bold"), size = size, hjust=0.5, vjust=0.5) +
xlab('') + ylab('') + labs(fill = '') + ggtitle('Example') +
theme(axis.text.y = element_text(size=14,face="bold"),
panel.background = element_blank(),
plot.title = element_text(size = 20, colour = "black", face = "bold"))
p
As far as I can see, the issue is caused by the facets since this slightly simplified version (i.e. without the facets) works fine:
library(ggplot2)
library(plyr)
library(scales)
Var1 = as.factor(c("A", "B", "C", "D", "E", "F"))
Freq = c(0.4, 0.1, 0.3, 0.1, 0.05, 0.05)
y = cumsum(Freq)-Freq/2
Data = data.frame(Var1, Freq, y)
size = ifelse(Data$Freq > 0.05, 10, 3)
label = paste(round(Data$Freq*100,0),"%", sep = "")
p = ggplot(data = Data, aes(x = factor(''), y = Freq, fill = Var1)) +
geom_bar(stat = "identity",position = "fill", width = 1) +
scale_fill_brewer(palette = 3) +
geom_text(aes(y = y, label = label,
position ="identity", face = "bold"), size = size, hjust=0.5, vjust=0.5) +
xlab('') + ylab('') + labs(fill = '') + ggtitle('Example') +
theme(axis.text.y = element_text(size=14,face="bold"),
panel.background = element_blank(),
plot.title = element_text(size = 20, colour = "black", face = "bold"))
p
By adding a size to your data frame and moving those parameters within your geom_text aes()` this seems to plot ok for me. I think..
Data$size <- size
p <- ggplot(data = Data, aes(x = factor(''), y = Freq, fill = Var1)) +
geom_bar(stat = "identity",position = "fill", width = 1) +
scale_fill_brewer(palette = 3) +
geom_text(aes(y = y, label = label,
position ="identity", face = "bold", size = size), hjust=0.5,
vjust=0.5) +
xlab('') + ylab('') + labs(fill = '') + ggtitle('Example') +
theme(axis.text.y = element_text(size=14,face="bold"),
panel.background = element_blank(),
plot.title = element_text(size = 20, colour = "black", face = "bold")) +
facet_grid(facets = . ~ Var2) +
guides(size=FALSE)
Also if you add + guides(size=FALSE) to the end as I have done this will remove your size legend.
My explanation for this, might be wrong, is that once you facet you were still providing a full length size and not allowing facet to chop the size data according to Var2 .
I think your problem with the sizing is that size you only have two sizes you are getting big differences (there must be some relative scaling maybe), perhaps add + scale_size(range=c(6,10)) and play with this to get something more appropriate? The 6,10 size range looks much better to me.

Resources