Why are Y axis labels offset in ggplot? - ggplot2

The Y axis labels are offset
The Y axis labels from 100 to the top are aligned to the right, while from 90 to the bottom are aligned to the left. I've looked at many paramaters and I couldn't find one to be causing this. Also, I haven't found anyone else with this same issue.
Here's my code:
test <- ggplot(data,
aes(x=Month, y=Value, color=Name, group=Name, fill=Name))+
geom_line(size=3)+
geom_point(size=5)+
scale_color_manual(values=c("#FBE785","#0F5F00","#FFC300","#1BFFAA"))+
ylab ("")+
xlab ("")+
labs(caption = paste("Fonte: Fred e IBGE.")) +
scale_x_date(date_labels = "%b/%y", breaks = "6 month", expand=c(0,0))+
coord_cartesian(clip = "off")+
theme_minimal() +
guides(fill=guide_legend())+
theme(panel.background = element_rect(fill= "#122929",color = "#122929"),
plot.background = element_rect(fill = "#122929"),
panel.grid.major = element_line(color = "#4D4B55", size =0.1),
panel.grid.minor = element_line(color= "#4D4B55", size =0.1),
panel.grid = element_blank(),
axis.text.y = element_text(vjust = 1, hjust=-1),
axis.text.x = element_text(vjust = -1, hjust=0),
legend.title = element_blank(),
legend.position = "bottom",
legend.key.width = unit(1.5, "cm"),
plot.caption = element_text(family = "Abel",vjust = -1, hjust = 0,colour="#4D4B55", size= 30),
text = element_text(family = "Abel", color = "#4D4B55",size = 35),
plot.margin = margin(1,1,1.5,1.2, "cm"))
ggsave("./test.png", width = 21, height = 15, dpi = 300)
PS: Not sharing the data itself because I guess that's not where the problem is.
Thanks!

Your text is misaligned because of your axis.text.y argument. Change hjust to 1 and it will be properly aligned. I have provided a minimal reproducible example below.
library(tidyverse)
Month <- rep(x = month.abb, times = 10)
Value <- sample(x = 10:120, size = 120, replace = TRUE)
Name <- sample(x = LETTERS[1:4], size = 120, replace = TRUE)
data <- data.frame(Month, Value, Name)
ggplot(data, aes(x = Month, y = Value, color = Name, group = Name, fill = Name)) +
geom_line(size = 1) + geom_point(size = 2) +
theme(axis.text.y = element_text(vjust = 1, hjust = 1)) # <- problem here

Related

Mismatch when using ggplot2 with a geom_point conditional fill

I am trying to have a white fill, for models where the p.fdr variable is <0.05.
However, the code I have written, is not modifying the correct point (the blue estimate should have a white fill not the pink estimate, as pictured below).
Example code:
conf.low <- sort(runif(6, min = 0, max = 1))
conf.high <- sort(runif(6, min = conf.low[1], max = 1))
estimate <- (conf.low + conf.high) / 2
forestplot <- data.frame(
outcome = c("mean_ssrt_0","mean_ssrt_0", "strp_scr_mnrt_congr", "strp_scr_mnrt_congr", "nihtbx_picvocab_theta_0","nihtbx_picvocab_theta_0"),
measure = c("Stop-Signal Task", "Stop-Signal Task","Emotional Word-Emotional Face Stroop", "Emotional Word-Emotional Face Stroop","NIH Toolbox® Cognition Battery", "NIH Toolbox® Cognition Battery" ),
a_model = c("1", "2", "1", "2", "1", "2"),
conf.low = conf.low,
conf.high = conf.high,
estimate = estimate,
p.fdr = runif(6, min = 0.05 / 1.3, max = 0.1))
forestplot$outcome <- factor(forestplot$outcome, levels=c('mean_ssrt_0', 'strp_scr_mnrt_congr', 'nihtbx_picvocab_theta_0'),
labels=c("Mean SSRT", "RT", "PVT \n (Theta)"))
forestplot$measure <- factor(forestplot$measure, levels=c('Stop-Signal Task',
'Emotional Word-Emotional Face Stroop',
'NIH Toolbox® Cognition Battery'))
forestplot$a_model <- factor(forestplot$a_model , levels=c("1","2"))
forestplot <- forestplot %>% arrange(measure, outcome,a_model, estimate, conf.low, conf.high)
plots <- forestplot %>%
split(.$measure) %>%
map2(.,names(.), ~ggplot(.x, aes(x = outcome, y =estimate, ymin =conf.low, ymax = conf.high,fill = as.factor(measure))) +
geom_pointrange(aes(color=a_model, shape = a_model), size=0.5, position=position_dodge2(width=0.5, reverse = TRUE), show.legend = F)+ # add group
geom_point(aes(shape = a_model), size=1.5, alpha = ifelse(.x$p.fdr < 0.05, 1, 0), position=position_dodge2(width=0.5, reverse = TRUE), show.legend = F, color="white") +
geom_hline(yintercept = 0, linetype = 'dashed', col = 'black') +
scale_y_continuous(limits = c(-0.1, 1))+
coord_flip() +
xlab('')+
ylab(expression(atop("Est. mean change (in SD units with 95% CI)", paste("per 1 SD increase in gPFS"^"lowDA"))))+
ggtitle(.y)+
theme_minimal(base_size = 11)+
guides(fill = "none") +
scale_color_manual(labels = c("Model 1", "Model 2"), values = c("#00B8E7", "#F8766D")) +
labs(color="Model")+
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title.position = "plot",
plot.title = element_text(size = 10,face="bold"), text = element_text(size = 10)))
plot <-plot_grid(plots$`Stop-Signal Task`+ ggtitle(bquote(bold(~ "Stop-Signal Task" ~ '')))+ theme(legend.position = "none", axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.text.x = element_blank(),axis.line.y = element_line(color="black", size = 0.5)),
plots$`Emotional Word-Emotional Face Stroop` + ggtitle(bquote(bold(~ 'Stroop - EWEFS' ~ ''))) + theme(legend.position = "none", axis.title.x = element_blank(), axis.ticks.x = element_blank(), axis.text.x = element_blank(),axis.line.y = element_line(color="black", size = 0.5)),
plots$`NIH Toolbox® Cognition Battery` + ggtitle(bquote(bold(~ "NIH Toolbox\U00AE" ~ ''))) + theme(legend.position = "none", axis.ticks.x = element_line(color="black", size = 0.5), axis.line.x = element_line(color="black", size = 0.5),axis.line.y = element_line(color="black", size = 0.5)),
ncol = 1, nrow=3, rel_heights = c(1,1,1), align = 'v') # add 1 col and then the number of rows = to number of plots
plot
I have tried arranging the ordering the original dataframe but, it doesn't solve the problem.
forestplot <- forestplot %>% arrange(measure, outcome, a_model, estimate, conf.low, conf.high)
Is it okay if instead of white fill, it's just transparent? You can control that through the shape argument. It also simplifies the code a little bit. This is how you would modify your plots object:
plots <- forestplot %>%
mutate(
shape = if_else(a_model == 1 & p.fdr < 0.05, "hollow_circle",
if_else(a_model == 1 & p.fdr >= 0.05, "filled_circle",
if_else(a_model == 2 & p.fdr < 0.05, "hollow_triangle", "filled_triangle")))
) %>%
split(.$measure) %>%
map2(.,names(.), ~ggplot(.x, aes(x = outcome, y = estimate, ymin = conf.low, ymax = conf.high, shape = shape, color = a_model)) +
geom_pointrange(size = 0.5, position = position_dodge2(width = 0.5, reverse = TRUE), show.legend = F) + # add group
geom_hline(yintercept = 0, linetype = 'dashed', col = 'black') +
scale_y_continuous(limits = c(-0.1, 1)) +
scale_shape_manual(values = c("filled_circle" = 16, "hollow_triangle" = 2, "hollow_circle" = 1, "filled_triangle" = 17)) +
coord_flip() +
xlab('')+
ylab(expression(atop("Est. mean change (in SD units with 95% CI)", paste("per 1 SD increase in gPFS"^"lowDA"))))+
ggtitle(.y)+
theme_minimal(base_size = 11)+
guides(fill = "none") +
scale_color_manual(values = c("1" = "#00B8E7", "2" = "#F8766D")) +
theme(panel.grid.major = element_blank(),
panel.grid.minor = element_blank(),
plot.title.position = "plot",
plot.title = element_text(size = 10,face="bold"), text = element_text(size = 10)))

My ggplot includes geom_boxplot and geom_line, but it does not show the legend for the geom_line part. How can I add it please?

My ggplot includes geom_boxplot and geom_line, but it only shows the legend for the boxplot part but does not show the legend for the geom_line part. How can I add it please?
Note: The boxplot and the line were made from two different data sources, but shown in one graph.
I really need help with this please, thank you!
Here is the code:
library(ggnewscale)
bplot6 <- ggplot(seasonalmerge_neale1989) +
geom_boxplot(aes(x = date, y = values, group = date, fill = `Data Source`), width = 2, outlier.shape = NA,
lwd = 0.1) +
xlab("") +
ylab("") +
ylim(0,1.2) +
theme(
axis.text.x = element_text(family="serif", size = 8),
axis.text.y = element_text(family="serif", size = 8),
legend.title = element_text(family="serif", size = 8),
legend.text = element_text(family="serif", size = 8),
plot.title = element_text(family="serif", face="bold", size = 8, hjust = 0.5)) +
ggtitle("(f)")+
new_scale_color() +
geom_line(data=pointframe, aes(x= pointdate, y=pointvar), colour="gold", size=1, method = "lm", se=FALSE)
# +theme_classic()+scale_linetype_manual(values=bplot6, name="Data Source: ", labels=c("Ceres", "Landsat", "FAO"))+ theme(legend.position = "bottom")
bplot6
image of boxplots and line
A color must be specified inside an aesthetic in order for there to be a legend.
Moving colour inside aes() will build a legend automatically. Then we can adjust the labels and colors with scale_color_manual. Reproducing your code using iris data.
library(ggnewscale)
bplot6 <- ggplot(iris) +
geom_boxplot(aes(x = Petal.Length, y = Petal.Width , group = Species, fill = `Species`), width = 2, outlier.shape = NA,lwd = 0.1) +
xlab("") +
ylab("") +
#ylim(0,1.2) + you can use it as per your requirement
theme(
axis.text.x = element_text(family="serif", size = 8),
axis.text.y = element_text(family="serif", size = 8),
legend.title = element_text(family="serif", size = 8),
legend.text = element_text(family="serif", size = 8),
plot.title = element_text(family="serif", face="bold", size = 8, hjust = 0.5)) +
ggtitle("(f)")+
new_scale_color() +
geom_line(data=iris, aes(x= Sepal.Length, y=Sepal.Width, color="Gold"), size=1)+
scale_color_manual(name = "Colour", values = c("Gold" = "gold"))
# +theme_classic()+scale_linetype_manual(values=bplot6, name="Data Source: ", labels=c("Ceres", "Landsat", "FAO"))+ theme(legend.position = "bottom")
bplot6

Facet title left alignment using facet_grid

I'm making a plot with facets where the length of facet titles vary quite a bit. I am trying to left-align the facet/strip title with hjust, but it seems like hjust adjust differently depending on length of each facet title. Ideally, I would like to align each facet title with the 0 on the axis.
library(ggplot2)
data <- data.frame(q = c(rep("q1", 16), rep("question mucher longer and longer and longer", 16)),
cat = c(rep(paste0("cat", 1:4), times = 8)),
p = rep(25, 32),
group = c(rep(paste0("group", 1:4), each = 4),
c(rep(paste0("group", 1:4), each = 4))))
ggplot(data = data,
aes(x = group, y = p, fill = cat, label = p)) +
geom_bar(stat="identity", position = position_stack(), width=0.6) +
facet_grid(col = vars(q)) +
coord_flip() +
geom_text(position = position_stack(vjust = 0.5), size = 3.5, color= "black") +
xlab("") +
ylab("") +
theme_minimal(base_size=12) +
theme(
legend.position="bottom",
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line( size=.1, color="gray"),
panel.grid.minor.x = element_line( size=.1, color="gray"),
strip.text = element_text(face="bold", hjust=0.03)) +
guides(fill = guide_legend(reverse=TRUE)) +
scale_y_continuous(labels=c("0","25","50","75","100 %")) +
geom_hline(yintercept = 0, color = "gray23") +
geom_hline(yintercept = 100, color = "gray23") +
theme(legend.title=element_blank(),
legend.margin=margin(0,0,0,0),
legend.box.margin=margin(-10,0,0,0))
The issue is the expansion of the y scale. Hence, the strip text box expands over the 0 line. To fix your issue use hjust=0 for the strip box text and remove the default expansion on the left (or bottom in your case) of the y scale. To show this clearer I added a red box around the strip text boxes:
library(ggplot2)
ggplot(
data = data,
aes(x = group, y = p, fill = cat, label = p)
) +
geom_bar(stat = "identity", position = position_stack(), width = 0.6) +
facet_grid(col = vars(q)) +
coord_flip() +
geom_text(position = position_stack(vjust = 0.5), size = 3.5, color = "black") +
xlab("") +
ylab("") +
theme_minimal(base_size = 12) +
theme(
legend.position = "bottom",
panel.grid.major.y = element_blank(),
panel.grid.major.x = element_line(size = .1, color = "gray"),
panel.grid.minor.x = element_line(size = .1, color = "gray"),
strip.text = element_text(face = "bold", hjust = 0, margin = margin(0, 0, 0, 0, "pt")),
strip.background.x = element_rect(color = "red")
) +
guides(fill = guide_legend(reverse = TRUE)) +
scale_y_continuous(labels = c("0", "25", "50", "75", "100 %"), expand = c(0, 0, .05, 0)) +
geom_hline(yintercept = 0, color = "gray23") +
geom_hline(yintercept = 100, color = "gray23") +
theme(
legend.title = element_blank(),
legend.margin = margin(0, 0, 0, 0),
legend.box.margin = margin(-10, 0, 0, 0)
)

Start ggplot continuous axis with a squiggly line break? [duplicate]

I have a dataframe (dat) with two columns 1) Month and 2) Value. I would like to highlight that the x-axis is not continuous in my boxplot by interrupting the x-axis with two angled lines on the x-axis that are empty between the angled lines.
Example Data and Boxplot
library(ggplot2)
set.seed(321)
dat <- data.frame(matrix(ncol = 2, nrow = 18))
x <- c("Month", "Value")
colnames(dat) <- x
dat$Month <- rep(c(1,2,3,10,11,12),3)
dat$Value <- rnorm(18,20,2)
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"))
The ideal figure would look something like below. How can I make this discontinuous axis in ggplot?
You could make use of the extended axis guides in the ggh4x package. Alas, you won't easily be able to create the "separators" without a hack similar to the one suggested by user Zhiqiang Wang
guide_axis_truncated accepts vectors to define lower and upper trunks. This also works for units, by the way, then you have to pass the vector inside the unit function (e.g., trunc_lower = unit(c(0,.45), "npc") !
library(ggplot2)
library(ggh4x)
set.seed(321)
dat <- data.frame(matrix(ncol = 2, nrow = 18))
x <- c("Month", "Value")
colnames(dat) <- x
dat$Month <- rep(c(1,2,3,10,11,12),3)
dat$Value <- rnorm(18,20,2)
# this is to make it slightly more programmatic
x1end <- 3.45
x2start <- 3.55
p <-
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
theme_classic() +
theme(axis.line = element_line(colour = "black"))
p +
guides(x = guide_axis_truncated(
trunc_lower = c(-Inf, x2start),
trunc_upper = c(x1end, Inf)
))
Created on 2021-11-01 by the reprex package (v2.0.1)
The below is taking user Zhiqiang Wang's hack a step further. You will see I am using simple trigonometry to calculate the segment coordinates. in order to make the angle actually look as it is defined in the function, you would need to set coord_equal.
# a simple function to help make the segments
add_separators <- function(x, y = 0, angle = 45, length = .1){
add_y <- length * sin(angle * pi/180)
add_x <- length * cos(angle * pi/180)
## making the list for your segments
myseg <- list(x = x - add_x, xend = x + add_x,
y = rep(y - add_y, length(x)), yend = rep(y + add_y, length(x)))
## this function returns an annotate layer with your segment coordinates
annotate("segment",
x = myseg$x, xend = myseg$xend,
y = myseg$y, yend = myseg$yend)
}
# you will need to set limits for correct positioning of your separators
# I chose 0.05 because this is the expand factor by default
y_sep <- min(dat$Value) -0.05*(min(dat$Value))
p +
guides(x = guide_axis_truncated(
trunc_lower = c(-Inf, x2start),
trunc_upper = c(x1end, Inf)
)) +
add_separators(x = c(x1end, x2start), y = y_sep, angle = 70) +
# you need to set expand to 0
scale_y_continuous(expand = c(0,0)) +
## to make the angle look like specified, you would need to use coord_equal()
coord_cartesian(clip = "off", ylim = c(y_sep, NA))
I think it is possible to get what you want. It may take some work.
Here is your graph:
library(ggplot2)
set.seed(321)
dat <- data.frame(matrix(ncol = 2, nrow = 18))
x <- c("Month", "Value")
colnames(dat) <- x
dat$Month <- rep(c(1,2,3,10,11,12),3)
dat$Value <- rnorm(18,20,2)
p <- ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black"))
Here is my effort:
p + annotate("segment", x = c(3.3, 3.5), xend = c(3.6, 3.8), y = c(14, 14), yend = c(15, 15))+
coord_cartesian(clip = "off", ylim = c(15, 25))
Get something like this:
If you want to go further, it may take several tries to get it right:
p + annotate("segment", x = c(3.3, 3.5), xend = c(3.6, 3.8), y = c(14, 14), yend = c(15, 15))+
annotate("segment", x = c(0, 3.65), xend = c(3.45, 7), y = c(14.55, 14.55), yend = c(14.55, 14.55)) +
coord_cartesian(clip = "off", ylim = c(15, 25)) +
theme_classic()+
theme(axis.line.x = element_blank())
Just replace axis with two new lines. This is a rough idea, it may take some time to make it perfect.
You could use facet_wrap. If you assign the first 3 months to one group, and the other months to another, then you can produce two plots that are side by side and use a single y axis.
It's not exactly what you want, but it will show the data effectively, and highlights the fact that the x axis is not continuous.
dat$group[dat$Month %in% c("1", "2", "3")] <- 1
dat$group[dat$Month %in% c("10", "11", "12")] <- 2
ggplot(data = dat, aes(x = factor(Month), y = Value)) +
geom_boxplot() +
labs(x = "Month") +
theme_bw() +
theme(panel.grid = element_blank(),
text = element_text(size = 16),
axis.text.x = element_text(size = 14, color = "black"),
axis.text.y = element_text(size = 14, color = "black")) +
facet_wrap(~group, scales = "free_x")
* Differences in the plot are likely due to using different versions of R where the set.seed gives different result

The second description of the x-axis in ggplot2?

I am wondering if there is a way to add the second description of x-axis in ggplot2 as follows: Here "the second description" refers "Sample A / Sample B / two arrows" colored in red (shown in the figure).
Please click for the figure!
Of course, I can just put the "second description" using PowerPoint as I did, but I just wonder if it is possible to add it using ggplot2.
Here is the code for the background plot.
library(ggplot2)
library(ggridges)
x <- data.frame(v1=rnorm(100, mean = -2, sd = 0.022),
v2=rnorm(100, mean = -1, sd = 0.022),
v3=rnorm(100, mean = 0, sd = 0.022),
v4=rnorm(100, mean = 1, sd = 0.022),
v5=rnorm(100, mean = 2, sd = 0.022),
v6=rnorm(100, mean = 3, sd = 0.022),
v7=rnorm(100, mean = 4, sd = 0.022))
colnames(x) <- c("A",
"B",
"C",
"D",
"E",
"F",
"G")
head(x)
# Manipulate the data
library(reshape2)
data <- melt(x)
head(data)
# Generating plot
colors <- rainbow(7)
ggplot(data, aes(x = value, y = variable)) +
geom_density_ridges(aes(fill = variable), alpha=0.6, bandwidth=0.1) +
scale_fill_manual(values = colors)+
theme(axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
legend.text = element_text(size = 12),
plot.title = element_text(size = 17, face = "bold",
margin = margin(b=10), hjust = 0.5),
panel.spacing = unit(0.1, "lines"),
legend.position="none") +
geom_vline(xintercept = 0, linetype="dotted") +
geom_vline(xintercept = 2, linetype="dotted",
color = "red", size=1.2) +
xlab("") +
ylab("Groups") +
labs(title = 'Density plot of each group')
Thank you in advance!
I'm not 100% sure this is what you mean, but you can add text on the x-axis using the following in labs:
labs(x="← Sample A Sample B →")
I got the arrows from unicode here: http://xahlee.info/comp/unicode_arrows.html
There are bigger arrows in the link if needed.
EDIT:
Here's your code adapted with the new labels in red font:
ggplot(data, aes(x = value, y = variable)) +
geom_density_ridges(aes(fill = variable), alpha=0.6, bandwidth=0.1) +
scale_fill_manual(values = colors)+
theme(axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
legend.text = element_text(size = 12),
plot.title = element_text(size = 17, face = "bold",
margin = margin(b=10), hjust = 0.5),
panel.spacing = unit(0.1, "lines"),
legend.position="none") +
geom_vline(xintercept = 0, linetype="dotted") +
geom_vline(xintercept = 2, linetype="dotted",
color = "red", size=1.2) +
xlab("🢀 Sample A Sample B 🢂") +
theme(axis.title.x = element_text(size=40,colour = "red")) +
ylab("Groups") +
labs(title = 'Density plot of each group')
You can also push the labels further apart by adding extra spaces. Bring them closer together with fewer spaces.