Hide specific facet axis labels in ggplot - r

you'll see with the code below that I end up with a nicely faceted plot that looks how I need it, but all I want is to hide the y axis labels for all facets except the ones on the far left. So hide labels for facet 2, 3, 4, 6, and 7. That way I am just left with "White", "Black", and "Hispanic" on the far left of each row (I can clean up the prefix_ later). Any ideas?
d2 %>%
ggplot(., aes(x = var_new, y = coef,
ymin = ci_lower, ymax = ci_upper)) +
geom_point(color = "red") +
geom_errorbar(width = 0,
size = 1,
color = "red") +
facet_wrap(~model,
nrow = 2,
scales = "free") +
geom_hline(yintercept = 0, linetype = "dashed", color = "black", size = .3) +
coord_flip() +
theme_minimal(base_size = 10) +
theme(legend.position = "none")
structure(list(model = c(7, 6, 5, 7, 6, 5, 7, 6, 5, 4, 3, 4,
3, 4, 3, 2, 1, 2, 1, 2, 1), race = c("hispanic", "hispanic",
"hispanic", "black", "black", "black", "white", "white", "white",
"hispanic", "hispanic", "black", "black", "white", "white", "hispanic",
"hispanic", "black", "black", "white", "white"), var_new = c("ela_hispanic",
"math_hispanic", "sci_hispanic", "ela_black", "math_black", "sci_black",
"ela_white", "math_white", "sci_white", "after_hispanic", "before_hispanic",
"after_black", "before_black", "after_white", "before_white",
"part_hispanic", "full_hispanic", "part_black", "full_black",
"part_white", "full_white"), coef = c(0.91, 0.2615005, -0.0622102,
3.1966945, 0.9665615, 0.4419779, -4.1608082, -1.75, -3.4185874,
-1.72661788, -1.87514649, 0.61605887, 0.58634364, 0.87, 0.4,
1.52820746, 1.35976557, 1.08885352, 0.8323809019, 0.728991331,
1.53140561), ci_lower = c(0.3, -1.04316665, -1.68479242, -1.0382233,
-0.70264707, -1.29579134, -12.008101, -3, -6.4522842, -1.9858909,
-2.10047863, 0.41173674, 0.37007869, -0.3428254, -0.1, 1.21339829,
1.07813362, 0.778488586, 0.44183285, 0.30081336, 0.98770764),
ci_upper = c(1.2, 1.748, 1.560372, 7.4316126, 2.63577, 2.179747,
3.6864845, 0.01, -0.3848905, -1.467344828, -1.64981433, 0.8203809961,
0.802608596, 0.4, 0.8, 1.8430166, 1.64139752, 1.39921842,
1.22292898, 1.15716932, 2.0751036)), row.names = c(NA, -21L
), class = c("tbl_df", "tbl", "data.frame"))

I don't understand why folks continue to switch the x and y axis variables then use coord_flip to put them round the right way. This is confusing, unnecessary, and requires more code. It's best to just put the variables round the right way and keep the coord as-is.
Once that's done, the simplest solution is to put race on the y axis, and change scales to free_x. I've added a border around each panel to make things a bit clearer.
library(tidyverse)
ggplot(d2, aes(y = race, x = coef, xmin = ci_lower, xmax = ci_upper)) +
geom_errorbar(width = 0, linewidth = 1.5, color = "red3", alpha = 0.5) +
geom_point(shape = 21, fill = "red2", size = 3, color = 'white') +
facet_wrap(~ model, nrow = 2, scales = 'free_x') +
geom_vline(xintercept = 0, linetype = "dashed", linewidth = 0.3) +
theme_minimal(base_size = 14) +
theme(legend.position = "none",
panel.grid.major.y = element_blank(),
panel.border = element_rect(color = 'gray75', fill = NA))
If you want to include the prefixes in the facet titles (since they have a 1:1 correspondence with model), you could use tidyr::separate:
d2 %>%
separate(var_new, into = c('model_name', 'race')) %>%
mutate(model = paste(model, model_name, sep = ' - ')) %>%
ggplot(aes(y = race, x = coef, xmin = ci_lower, xmax = ci_upper)) +
geom_errorbar(width = 0, linewidth = 1.5, color = "red3", alpha = 0.5) +
geom_point(shape = 21, fill = "red2", size = 3, color = 'white') +
facet_wrap(~model, nrow = 2, scales = 'free_x') +
geom_vline(xintercept = 0, linetype = "dashed", linewidth = 0.3) +
theme_minimal(base_size = 14) +
theme(legend.position = "none",
panel.grid.major.y = element_blank(),
panel.border = element_rect(color = 'gray75', fill = NA))
Addendum
To compare coefficients across groups like this, it is normally better to put them all in a single linerange plot (similar to a forest plot). I think this provides a much better visualization that requires less cognitive effort from the reader. This also shows a good use-case for coord_flip, namely when you want a vertical dodge between groups.
d2 %>%
separate(var_new, into = c('model_name', 'race')) %>%
mutate(model = paste0('Model ', model, ' : ', model_name)) %>%
ggplot(aes(x = model, y = coef, ymin = ci_lower, ymax = ci_upper,
color = race)) +
annotate("segment", y = rep(-Inf, 3), yend = rep(Inf, 3),
x = c('Model 2 : part', 'Model 4 : after', 'Model 6 : math'),
xend = c('Model 2 : part', 'Model 4 : after', 'Model 6 : math'),
linewidth = 22, alpha = 0.05) +
coord_flip() +
geom_errorbar(width = 0, linewidth = 1, alpha = 0.5,
position = position_dodge(width = 0.5)) +
geom_point(size = 1.5, position = position_dodge(width = 0.5)) +
geom_hline(yintercept = 0, linetype = "dashed", color = "black",
linewidth = 0.3) +
scale_color_brewer(palette = 'Set1') +
theme_minimal(base_size = 14) +
guides(color = guide_legend(reverse = TRUE)) +
theme(panel.grid.major.y = element_blank(),
panel.border = element_rect(color = 'gray75', fill = NA),
axis.text.y = element_text(hjust = 0))

Related

Plot breaks due to deprecated function

I am trying to reproduce the plot from this question, but code is deprecated and I cant seem to figure out why it always gives the error.
Error: Discrete value supplied to continuous scale.
I thought I had omitted each row for being discrete to figure uot what was going on, but anyway I do it it alyways breaks because of that. There are some minor errors due to axis.ticks.margin and panel.margin as well as vjust but I don think they are the main issue. Although not 100%.
Find the reproducible dataset here:
groupData <- dput(structure(list(ID = 1:12, Group = c("Renal Failure", "Renal Failure",
"Diabetes", "Diabetes", "PA Disease", "PA Disease", "CV Disease",
"CV Disease", "Sex", "Sex", "Age", "Age"), Subgroup = c("No",
"Yes", "No", "Yes", "No", "Yes", "No", "Yes", "Female", "Male",
">70 yr", "<70 yr"), NoP = c(4594L, 66L, 2523L, 2228L, 4366L,
385L, 4296L, 456L, 908L, 3843L, 1935L, 2815L), P_S = c(0.2, 0.37,
0.84, 0.06, 0.37, 0.33, 0.18, 0.69, 0.21, 0.47, 0.17, 0.77),
P_G = c(0.51, 0.51, 0.13, 0.13, 0.54, 0.54, 0.41, 0.41, 0.46,
0.46, 0.46, 0.46)), class = "data.frame", row.names = c(NA, -12L)))
Code
## REQUIRED PACKAGES
require(grid)
require(ggplot2)
require(plyr)
############################################
### CUSTOMIZE APPEARANCE WITH THESE ####
############################################
blankRows<-2 # blank rows under boxplot
titleSize<-4
dataSize<-4
boxColor<-"pink"
############################################
############################################
## BASIC THEMES (SO TO PLOT BLANK GRID)
theme_grid <- theme(
axis.line = element_blank(),
axis.text.x = element_blank(),
axis.text.y = element_blank(),
axis.ticks = element_blank(),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.ticks.length = unit(0.0001, "mm"),
axis.ticks.margin = unit(c(0,0,0,0), "lines"),
legend.position = "none",
panel.background = element_rect(fill = "transparent"),
panel.border = element_blank(),
panel.grid.major = element_line(colour="grey"),
panel.grid.minor = element_line(colour="grey"),
panel.margin = unit(c(-0.1,-0.1,-0.1,-0.1), "mm"),
plot.margin = unit(c(5,0,5,0.01), "mm")
)
theme_bare <- theme_grid +
theme(
panel.grid.major = element_blank(),
panel.grid.minor = element_blank()
)
## LOAD GROUP DATA AND P values from csv file
groupData
## SYNTHESIZE SOME PLOT DATA - you can load csv instead
## EXPECTS 2 columns - integer for 'ID' matching groupdatacsv
## AND 'HR' Hazard Rate
hazardData<-expand.grid(ID=1:nrow(groupData),HR=1:6)
hazardData$HR<-1.3-runif(nrow(hazardData))*0.7
hazardData<-rbind(hazardData,ddply(groupData,.(Group),summarize,ID=max(ID)+0.1,HR=NA)[,2:3])
hazardData<-rbind(hazardData,data.frame(ID=c(0,-1:(-2-blankRows),max(groupData$ID)+1,max(groupData$ID)+2),HR=NA))
## Make the min/max mean labels
hrlabels<-ddply(hazardData[!is.na(hazardData$HR),],.(ID),summarize,lab=paste(round(mean(HR),2)," (",round(min(HR),2),"-",round(max(HR),2),")",sep=""))
## Points to plot on the log scale
scaledata<-data.frame(ID=0,HR=c(0.2,0.6,0.8,1.2,1.8))
## Pull out the Groups & P values
group_p<-ddply(groupData,.(Group),summarize,P=mean(P_G),y=max(ID)+0.1)
## identify the rows to be highlighted, and
## build a function to add the layers
hl_rows<-data.frame(ID=(1:floor(length(unique(hazardData$ID[which(hazardData$ID>0)]))/2))*2,col="lightgrey")
hl_rows$ID<-hl_rows$ID+blankRows+1
hl_rect<-function(col="white",alpha=0.5){
rectGrob( x = 0, y = 0, width = 1, height = 1, just = c("left","bottom"), gp=gpar(alpha=alpha, fill=col))
}
## DATA FOR TEXT LABELS
RtLabels<-data.frame(x=c(rep(length(unique(hazardData$ID))-0.2,times=3)),
y=c(0.6,6,10),
lab=c("Hazard Ratio\n(95% CI)","P Value","P Value for\nInteraction"))
LfLabels<-data.frame(x=c(rep(length(unique(hazardData$ID))-0.2,times=2)),
y=c(0.5,4),
lab=c("Subgroup","No. of\nPatients"))
LegendLabels<-data.frame(x=c(rep(1,times=2)),
y=c(0.5,1.8),
lab=c("Off-Pump CABG Better","On-Pump CABG Better"))
## BASIC PLOT
haz<-ggplot(hazardData,aes(factor(ID),HR))+ labs(x=NULL, y=NULL)
## RIGHT PANEL WITH LOG SCALE
rightPanel<-haz +
apply(hl_rows,1,function(x)annotation_custom(hl_rect(x["col"],alpha=0.4),as.numeric(x["ID"])-0.5,as.numeric(x["ID"])+0.5,-20,20)) +
geom_segment(aes(x = 2, y = 1, xend = 1.5, yend = 1)) +
geom_hline(aes(yintercept=1),linetype=2, linewidth=0.5)+
geom_boxplot(fill=boxColor,size=0.5, alpha=0.8)+
scale_y_log10() + coord_flip() +
geom_text(data=scaledata,aes(3,HR,label=HR), vjust=0.5, size=dataSize) +
geom_text(data=RtLabels,aes(x,y,label=lab, fontface="bold"), vjust=0.5, size=titleSize) +
geom_text(data=hrlabels,aes(factor(ID),4,label=lab),vjust=0.5, hjust=1, size=dataSize) +
geom_text(data=group_p,aes(factor(y),11,label=P, fontface="bold"),vjust=0.5, hjust=1, size=dataSize) +
geom_text(data=groupData,aes(factor(ID),6.5,label=P_S),vjust=0.5, hjust=1, size=dataSize) +
geom_text(data=LegendLabels,aes(x,y,label=lab, fontface="bold"),hjust=0.5, vjust=1, size=titleSize) +
geom_point(data=scaledata,aes(2.5,HR),shape=3,size=3) +
geom_point(aes(2,12),shape=3,alpha=0,vjust=0) +
geom_segment(aes(x = 2.5, y = 0, xend = 2.5, yend = 13)) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 1.8),arrow=arrow(),linetype=1,size=1) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 0.2),arrow=arrow(),linetype=1,size=1) +
theme_bare
## LEFT PANEL WITH NORMAL SCALE
leftPanel<-haz +
apply(hl_rows,1,function(x)annotation_custom(hl_rect(x["col"],alpha=0.4),as.numeric(x["ID"])-0.5,as.numeric(x["ID"])+0.5,-20,20)) +
coord_flip(ylim=c(0,5.5)) +
geom_point(aes(x=factor(ID),y=1),shape=3,alpha=0,vjust=0) +
geom_text(data=group_p,aes(factor(y),0.5,label=Group, fontface="bold"),vjust=0.5, hjust=0, size=dataSize) +
geom_text(data=groupData,aes(factor(ID),1,label=Subgroup),vjust=0.5, hjust=0, size=dataSize) +
geom_text(data=groupData,aes(factor(ID),5,label=NoP),vjust=0.5, hjust=1, size=dataSize) +
geom_text(data=LfLabels,aes(x,y,label=lab, fontface="bold"), vjust=0.5, hjust=0, size=4, size=titleSize) +
geom_segment(aes(x = 2.5, y = 0, xend = 2.5, yend = 5.5)) +
theme_bare
## PLOT THEM BOTH IN A GRID SO THEY MATCH UP
grid.arrange(leftPanel,rightPanel, widths=c(1,3), ncol=2, nrow=1)
The issue is that in your right panel plot you first map a continuous value on x via geom_segment and afterwards a discrete value via geom_boxplot. To fix that you could add a scale_x_discrete at the start of your code. Additionally I fixed the minor issues related to vjust in geom_point and a duplicated size argument in one of your geom_text layers.
## BASIC PLOT
haz <- ggplot(hazardData, aes(factor(ID), HR)) +
labs(x = NULL, y = NULL)
## RIGHT PANEL WITH LOG SCALE
rightPanel <- haz +
### Init the discrete x scale
scale_x_discrete() +
###
apply(hl_rows, 1, function(x) annotation_custom(hl_rect(x["col"], alpha = 0.4), as.numeric(x["ID"]) - 0.5, as.numeric(x["ID"]) + 0.5, -20, 20)) +
geom_segment(aes(x = 2, y = 1, xend = 1.5, yend = 1)) +
geom_hline(aes(yintercept = 1), linetype = 2, linewidth = 0.5) +
geom_boxplot(fill = boxColor, size = 0.5, alpha = 0.8) +
scale_y_log10() +
coord_flip() +
geom_text(data = scaledata, aes(3, HR, label = HR), vjust = 0.5, size = dataSize) +
geom_text(data = RtLabels, aes(x, y, label = lab, fontface = "bold"), vjust = 0.5, size = titleSize) +
geom_text(data = hrlabels, aes(factor(ID), 4, label = lab), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = group_p, aes(factor(y), 11, label = P, fontface = "bold"), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 6.5, label = P_S), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = LegendLabels, aes(x, y, label = lab, fontface = "bold"), hjust = 0.5, vjust = 1, size = titleSize) +
geom_point(data = scaledata, aes(2.5, HR), shape = 3, size = 3) +
geom_point(aes(2, 12), shape = 3, alpha = 0) +
geom_segment(aes(x = 2.5, y = 0, xend = 2.5, yend = 13)) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 1.8), arrow = arrow(), linetype = 1, size = 1) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 0.2), arrow = arrow(), linetype = 1, size = 1) +
theme_bare
## LEFT PANEL WITH NORMAL SCALE
leftPanel <- haz +
apply(hl_rows, 1, function(x) annotation_custom(hl_rect(x["col"], alpha = 0.4), as.numeric(x["ID"]) - 0.5, as.numeric(x["ID"]) + 0.5, -20, 20)) +
coord_flip(ylim = c(0, 5.5)) +
geom_point(aes(x = factor(ID), y = 1), shape = 3, alpha = 0) +
geom_text(data = group_p, aes(factor(y), 0.5, label = Group, fontface = "bold"), vjust = 0.5, hjust = 0, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 1, label = Subgroup), vjust = 0.5, hjust = 0, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 5, label = NoP), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = LfLabels, aes(x, y, label = lab, fontface = "bold"), vjust = 0.5, hjust = 0, size = titleSize) +
geom_segment(aes(x = 2.5, y = 0, xend = 2.5, yend = 5.5)) +
theme_bare
## PLOT THEM BOTH IN A GRID SO THEY MATCH UP
grid.arrange(leftPanel, rightPanel, widths = c(1, 3), ncol = 2, nrow = 1)
EDIT To get rid of the gap in your horizontal line and/or to extend the lines on the left and the right set yend=Inf and/or y=-Inf in the geom_segmentwhich draws the line.
library(gridExtra)
library(ggplot2)
## BASIC PLOT
haz <- ggplot(hazardData, aes(factor(ID), HR)) +
labs(x = NULL, y = NULL)
## RIGHT PANEL WITH LOG SCALE
rightPanel <- haz +
### Init the discrete x scale
scale_x_discrete() +
###
apply(hl_rows, 1, function(x) annotation_custom(hl_rect(x["col"], alpha = 0.4), as.numeric(x["ID"]) - 0.5, as.numeric(x["ID"]) + 0.5, -20, 20)) +
geom_segment(aes(x = 2, y = 1, xend = 1.5, yend = 1)) +
geom_hline(aes(yintercept = 1), linetype = 2, linewidth = 0.5) +
geom_boxplot(fill = boxColor, size = 0.5, alpha = 0.8) +
scale_y_log10() +
coord_flip() +
geom_text(data = scaledata, aes(3, HR, label = HR), vjust = 0.5, size = dataSize) +
geom_text(data = RtLabels, aes(x, y, label = lab, fontface = "bold"), vjust = 0.5, size = titleSize) +
geom_text(data = hrlabels, aes(factor(ID), 4, label = lab), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = group_p, aes(factor(y), 11, label = P, fontface = "bold"), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 6.5, label = P_S), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = LegendLabels, aes(x, y, label = lab, fontface = "bold"), hjust = 0.5, vjust = 1, size = titleSize) +
geom_point(data = scaledata, aes(2.5, HR), shape = 3, size = 3) +
geom_point(aes(2, 12), shape = 3, alpha = 0) +
geom_segment(aes(x = 2.5, y = 0, xend = 2.5, yend = Inf)) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 1.8), arrow = arrow(), linetype = 1, size = 1) +
geom_segment(aes(x = 2, y = 1, xend = 2, yend = 0.2), arrow = arrow(), linetype = 1, size = 1) +
theme_bare
## LEFT PANEL WITH NORMAL SCALE
leftPanel <- haz +
apply(hl_rows, 1, function(x) annotation_custom(hl_rect(x["col"], alpha = 0.4), as.numeric(x["ID"]) - 0.5, as.numeric(x["ID"]) + 0.5, -20, 20)) +
coord_flip(ylim = c(0, 5.5)) +
geom_point(aes(x = factor(ID), y = 1), shape = 3, alpha = 0) +
geom_text(data = group_p, aes(factor(y), 0.5, label = Group, fontface = "bold"), vjust = 0.5, hjust = 0, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 1, label = Subgroup), vjust = 0.5, hjust = 0, size = dataSize) +
geom_text(data = groupData, aes(factor(ID), 5, label = NoP), vjust = 0.5, hjust = 1, size = dataSize) +
geom_text(data = LfLabels, aes(x, y, label = lab, fontface = "bold"), vjust = 0.5, hjust = 0, size = titleSize) +
geom_segment(aes(x = 2.5, y = -Inf, xend = 2.5, yend = Inf)) +
theme_bare
## PLOT THEM BOTH IN A GRID SO THEY MATCH UP
grid.arrange(leftPanel, rightPanel, widths = c(1, 3), ncol = 2, nrow = 1)

Add id labels to points above the limit line in ggplot

I have a dataframe like this
id <- c(5738180,51845,167774,517814,1344920)
amount <- c(3.76765976,0.85195407,1.96821355,0.01464609,0.57378284)
outlier <- c("TRUE","FALSE","FALSE","FALSE","FALSE")
df.sample <- data.frame(id,amount,outlier)
I am trying to plot the points and add an id label to any point that is above the limit. In this case (id=5738180)
I am plotting like this
library(tidyverse)
library(ggplot2)
library(ggrepel) # help avoid overlapping text labels
library(gridExtra) # adds custom table inside ggplot
library(scales) # breaks and labels for axes and legends
library(ggthemes) # Adding desired ggplot themes
df.sample %>%
ggplot(aes(x = as.numeric(row.names(df.sample)),
y = amount, label = as.character(id))) +
geom_point(alpha = 0.6, position = position_jitter(w = 0.05, h = 0.0),
aes(colour = (amount < 3)), size = 2) +
geom_hline(aes(yintercept = 3, linetype = "Limit"),
color = 'black', size = 1) +
geom_text(aes(y = 3,x = amount[4],
label = paste("Limit = ", round(3, 3)),
hjust = 0, vjust = 1.5)) +
geom_text_repel(data = subset(df.sample, outlier == 'TRUE'),
nudge_y = 0.75,
size = 4,
box.padding = 1.5,
point.padding = 0.5,
force = 100,
segment.size = 0.2,
segment.color = "grey50",
direction = "x") +
geom_label_repel(data = subset(df.sample, outlier == 'TRUE'),
nudge_y = 0.75,
size = 4,
box.padding = 0.5,
point.padding = 0.5,
force = 100,
segment.size = 0.2,
segment.color = "grey50",
direction = "x")
labs(title = "Outlier Detection",
y = "amount",
x = "") +
theme_few() +
theme(legend.position = "none",
axis.text = element_text(size = 10, face = "bold"),
axis.title = element_text(size = 10, face = "bold"),
plot.title = element_text(colour = "blue", hjust = 0.5,
size = 15, face = "bold"),
strip.text = element_text(size = 10, face = "bold")) +
scale_colour_manual(values = c("TRUE" = "green","FALSE" = "red"))
I am running into an error "Error: Aesthetics must be either length 1 or the same as the data (1): x"
Can someone point me in the right direction?
The issue is with geom_text_repel() and geom_label_repel(). You subset the data, which now only includes 1 row, but the aes() are inheriting from the original data which have 5 rows, hence the error. To fix this, subset the data outside of the ggplot() call, and change the aesthetics for it. You are also missing a + after geom_label_repel() and the result below modifies the nudge_y to nudge_x and removes the geom_text_repel().
outliers <- subset(df.sample, outlier == TRUE)
ggplot(data = df.sample,
aes(x = as.numeric(row.names(df.sample)),
y = amount,
label = as.character(id))) +
geom_point(alpha = 0.6,
position = position_jitter(w = 0.05, h = 0.0),
aes(colour = (amount < 3)),
size = 2) +
geom_hline(aes(yintercept = 3,
linetype = "Limit"),
color = 'black',
size = 1) +
geom_text(aes(y = 3,x = amount[4],
label = paste("Limit = ",
round(3, 3)),
hjust = 0,
vjust = 1.5)) +
geom_label_repel(data = outliers,
aes(x = as.numeric(rownames(outliers)),
y = amount,
label = amount),
nudge_x = 0.75,
size = 4,
box.padding = 0.5,
point.padding = 0.5,
force = 100,
segment.size = 0.2,
segment.color = "grey50",
direction = "x",
inherit.aes = F) +
labs(title = "Outlier Detection",
y = "amount",
x = "") +
theme_few() +
theme(legend.position = "none",
axis.text = element_text(size = 10, face = "bold"),
axis.title = element_text(size = 10, face = "bold"),
plot.title = element_text(colour = "blue", hjust = 0.5,
size = 15, face = "bold"),
strip.text = element_text(size = 10, face = "bold")) +
scale_colour_manual(values = c("TRUE" = "green","FALSE" = "red"))

Aligned labels in several ggplots within a loop

I want to generate several plots for diferent categories, so I have the following code:
for (módulo in pruebas) {
plot <- ggplot(data = pruebas.oficiales[pruebas.oficiales$prueba==módulo,],
aes(y = Promedio.prueba, x = año)) +
geom_point(shape = 18, size = 4,
color = "#A32F4A") +
geom_errorbar(data = pruebas.oficiales[pruebas.oficiales$prueba==módulo,],
aes(ymin = Promedio.prueba - Desviacion,
ymax = Promedio.prueba + Desviacion),
color = "#A32F4A", width = 0.4, size = 1.3) +
theme(
panel.background = element_rect(fill = "white",
color = rgb(198, 198, 198,
maxColorValue = 255),
size = 1, linetype = "solid"),
panel.grid.minor = element_line(size = 0.1, linetype = "dashed",
color = rgb(198,198,198, maxColorValue = 255)),
axis.title = element_text(color = "#575756", family = "Montserrat"),
axis.text = element_text(family = "Montserrat")
) + geom_text(aes(label = Promedio.prueba), hjust = "left",
nudge_x = 0.145, show.legend = F, color = "#575756",
size = 4, family = "Montserrat") +
geom_text(aes(label = paste("(", Desviacion, ")")),
show.legend = F, color = "#575756", hjust = "left",
vjust = 2, nudge_x = 0.1, size = 4, family = "Montserrat") +
xlab(NULL) + ylab("Promedio de la prueba")
assign(paste0("plot.", módulo), plot)
}
If the corresponding "prueba" has four categories for the variable "año" I get a plot like
If the corresponding "prueba" has two categories for the variable "año" I get a plot like
For the latter, the upper labels are not align with the lower labels. Does anyone know how I can make all the plots have aligned labels regardless on the number of categories for "año" they have?

Adding variable name outside of panel/plot

Sample-data:
df <- data.frame("SL" = runif(50, 2.2, 5.8), "LMX" = runif(50, 1.8, 5.5))
I have many different variables for each of which I want to make a box plot with the code below. So that all panels will have the same size, I determined the plot margin so that it is not influenced by the length of the name of the variable. Therefore, now I want to add the variable name outside of the panel to the left.
However, this turns out to be more difficult than expected. I know that this issue has been raised before, but none of the solutions works with me (rnorm or geom_text).
Any help is much appreciated, thank you :)
df %>%
select("Servant Leadership" = SL) %>%
gather(key = "variable", value = "value") -> n
n$variable <- factor(n$variable, levels = c("Servant Leadership"))
ggplot(data = n, aes(y = value, x = as.numeric(variable))) +
stat_summary(fun.data = min.mean.sd.max, geom = "boxplot", col = "#323232", fill = "#EFC76C") +
scale_fill_identity() +
scale_x_continuous(breaks = as.numeric(unique(n$variable)), minor_breaks = NULL,
labels = "", expand = c(0.12, 0.12)) +
scale_y_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7)) +
expand_limits(y = c(1, 7)) + coord_flip() + labs(x = "", y = "") +
theme(text = element_text(size = 15), panel.background = element_rect(fill = "#EAEDED"),
panel.border = element_rect(fill=NA, color = "grey", size = 0.5, linetype = "solid")) +
theme(plot.margin=unit(c(0.2, 0.2, 0, 4),"cm"))
I forgot this code which I ran before:
min.mean.sd.max <- function(x) {
r <- c(min(x), mean(x) - sd(x), mean(x), mean(x) + sd(x), max(x))
names(r) <- c("ymin", "lower", "middle", "upper", "ymax")
r
}
And this are the packages which I use (maybe not all in this code however):
library(reshape)
library(scales)
library(ggplot2)
library(dplyr)
library(tidyr)
Based on the answer by Tung I amended the code for the box plot in the following way:
ggplot(data = n, aes(y = value, x = as.numeric(variable))) +
stat_summary(fun.data = min.mean.sd.max, geom = "boxplot", col = "#323232", fill = "#EFC76C") +
scale_fill_identity() +
scale_x_continuous(breaks = as.numeric(unique(n$variable)), minor_breaks = NULL,
labels = "", expand = c(0.12, 0.12)) +
scale_y_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7)) +
expand_limits(y = c(1, 7)) + coord_flip(clip = "off") + labs(x = "", y = "") +
theme(text = element_text(size = 18), panel.background = element_rect(fill = "#EAEDED"),
panel.border = element_rect(fill=NA, color = "grey", size = 0.5, linetype = "solid")) +
geom_text(x = 1, y = 0.5, inherit.aes = FALSE, label = "Servant Leadership", check_overlap = TRUE, hjust = 1,
fontface = 'plain', size = 6, color = "#4E4E4E") +
theme(plot.margin=unit(c(0.05, 4.5, 0, 9.5),"cm"))

Exact Positioning of multiple plots in ggplot2 with grid.arrange

I'm trying to create a multiple plot with the same x-axis but different y-axes, because I have values for two groups with different ranges. As I want to control the values of the axes (respectively the y-axes shall reach from 2.000.000 to 4.000.000 and from 250.000 to 500.000), I don't get along with facet_grid with scales = "free".
So what I've tried is to create two plots (named "plots.treat" and "plot.control") and combine them with grid.arrange and arrangeGrob. My problem is, that I don't know how to control the exact position of the two plots, so that both y-axes are positioned on one vertical line. So in the example below the second plot's y-axis needs to be positioned a bit more to the right.
Here is the code:
# Load Packages
library(ggplot2)
library(grid)
library(gridExtra)
# Create Data
data.treat <- data.frame(seq(2005.5, 2015.5, 1), rep("SIFI", 11),
c(2230773, 2287162, 2326435, 2553602, 2829325, 3372657, 3512437,
3533884, 3519026, 3566553, 3527153))
colnames(data.treat) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
data.control <- data.frame(seq(2005.5, 2015.5, 1), rep("Nicht-SIFI", 11),
c(324582, 345245, 364592, 360006, 363677, 384674, 369007,
343893, 333370, 318409, 313853))
colnames(data.control) <- c("Jahr", "treatment",
"Aggregierte Depositen (in Tausend US$)")
# Create Plot for data.treat
plot.treat <- ggplot() +
geom_line(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "dashed") +
geom_point(data = data.treat,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 24) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1),
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(2000000, 4000000, 500000),
minor_breaks = seq(2000000, 4000000, 250000),
labels = c("2.000.000", "2.500.000", "3.000.000",
"3.500.000", "4.000.000"),
limits = c(2000000, 4000000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(),
axis.title.y = element_blank(),
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(2000000),
xend = c(2008.7068),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 3875000, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(2000000),
xend = c(2010.5507),
yend = c(3750000)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 3875000, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Create Plot for data.control
plot.control <- ggplot() +
geom_line(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
size = 1,
linetype = "solid") +
geom_point(data = data.control,
aes(x = `Jahr`,
y = `Aggregierte Depositen (in Tausend US$)`),
fill = "white",
size = 2,
shape = 21) +
scale_x_continuous(breaks = seq(2005, 2015.5, 1), # x-Achse
minor_breaks = seq(2005, 2015.5, 0.5),
limits = c(2005, 2015.8),
expand = c(0.01, 0.01)) +
scale_y_continuous(breaks = seq(250000, 500000, 50000),
minor_breaks = seq(250000, 500000, 25000),
labels = c("250.000", "300.000", "350.000", "400.000",
"450.000", "500.000"),
limits = c(250000, 500000),
expand = c(0, 0.01)) +
theme(text = element_text(family = "Times"),
axis.title.x = element_blank(), # Achse
axis.title.y = element_blank(), # Achse
axis.line.x = element_line(color="black", size = 0.6),
axis.line.y = element_line(color="black", size = 0.6),
legend.position = "none") +
geom_segment(aes(x = c(2008.7068),
y = c(250000),
xend = c(2008.7068),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2008.7068, y = 484375, label = "Lehman\nBrothers + TARP",
colour = "black", size = 3, family = "Times") +
geom_segment(aes(x = c(2010.5507),
y = c(250000),
xend = c(2010.5507),
yend = c(468750)),
linetype = "dotted") +
annotate(geom = "text", x = 2010.5507, y = 484375, label = "Dodd-Frank-\nAct",
colour = "black", size = 3, family = "Times") +
geom_rect(aes(xmin = 2007.6027, xmax = 2009.5, ymin = -Inf, ymax = Inf),
fill="dark grey", alpha = 0.2)
# Combine both Plots with grid.arrange
grid.arrange(arrangeGrob(plot.treat, plot.control,
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))
Do:
install.packages("cowplot")
but do not library(cowplot) as it'll mess up your theme work.
Then, do:
grid.arrange(
arrangeGrob(cowplot::plot_grid(plot.treat, plot.control, align = "v", ncol=1),
ncol = 1,
left = textGrob("Aggregierte Depositen (in Tausend US$)",
rot = 90,
vjust = 1,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold")),
bottom = textGrob("Jahr",
vjust = 0.1,
hjust = 0.2,
gp = gpar(fontfamily = "Times",
size = 12,
colout = "black",
fontface = "bold"))))

Resources