Line break with x10^x notation ggplot title - r

I was able to get plots that look like the attached image by using "\n" for the line break. However, the problem is the 8.8e-14. The journal requests I change it to 8.8x10^14 (with the 14 in superscript). However, that only works if I use expression(paste). But in that case, the "\n" doesn't cause a line break anymore. I've spent about 5 hours trial and erroring through different solutions on the internet to no avail. Does anyone have a solution? Thanks in advance.
What I would like it to look like (except I would like it to say 8.8x10^14 instead):
The below works EXCEPT there's no line break (I would like a line break before "Interaction")
plot_fun_to_revise = function(x, y) {
ggplot(data = data_for_median_plots, aes(x = .data[[x]], y = .data[[y]], group = Secretor, linetype = Secretor)) +
stat_summary(geom = "line", fun.data = median_hilow, size = 0.5) +
stat_sum_df_all("median_hilow",
fun.args = (conf.int = 0.5),
linetype = "solid",
size = 0.5) +
theme_classic()
lnnt_plot_median <- plot_fun_to_revise("Timepoint", "LNnT") +
ylim(0,5000) +
labs(y = paste("LNnT", "(\u03BCg/mL)"),
title = expression(paste("Time p = 8.8 x", 10^-14, ", Secretor p = 0.35, Interaction p = 0.51")),
x = "Time (months postpartum)"

Obviously, I don't have your data to replicate the plot itself, but since this is about labelling anyway, let's just make an (essentially) empty plot:
lnnt_plot_median <- ggplot(data.frame(x = 1, y = 1), aes(x, y)) +
geom_point() +
theme_classic() +
theme(text = element_text(face = 2, size = 16),
plot.title = element_text(hjust = 0.5))
Since you are using unicode escapes already, I think the easiest thing to do here is use the unicode escapes for superscript 1 and superscript 4:
lnnt_plot_median +
labs(y = paste("LNnT", "(\u03BCg/mL)"),
title = paste("Time p = 8.8 x 10\u00b9\u2074,",
"Secretor p = 0.35,\n Interaction p = 0.51"),
x = "Time (months postpartum)")

Related

Points to flags in ggplot2

I would like to change the dots in the next plot to the flag for the respective country. For this I know that geom_flag() could works, but... not for me but I got stuck with this error message:
Error in grobify(picture, x = x, y = y, width = width, height = height, :
object '.flaglist' not found
This is my code:
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point()+ ggflags::geom_flag(aes(x = longitude, y = latitude+0.5, country = country))
maybe also geom_image() could work but I don't know how to link the flag with the country column...or How to use an image as a point in ggplot?, but I don't understand the process
This my desire plot, but changing dots to flags:
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point(aes(colour = factor(country)))+
scale_fill_brewer(palette = "Set3")+ scale_x_continuous(breaks = seq(10, 40, by = 5))+
scale_y_continuous(breaks = seq(0, 16, by = 1))+
theme_classic2() + theme_cleveland()+ geom_smooth(method = "lm", alpha=0.2)+
stat_cor(label.x = 2, label.y = 1)
This is my data:
https://drive.google.com/drive/folders/1qR2mUdrpStOYBmxajc_F4nxS_qf-4bzf?usp=sharing
thanks in advance
It seems to work for me if I convert your countries to two-character ISO codes (which is what the example at https://github.com/jimjam-slam/ggflags uses).
I also had to load the ggflags library, rather than using ggflags::geom_flag
For example, using the countrycode package:
df$iso_code <- tolower(countrycode(df$country, origin = 'country.name', destination = 'iso2c'))
ggplot(df, aes(lenght, Ponto.Caspian)) +
geom_point() +
geom_flag(aes(x = longitude, y = latitude+0.5, country = iso_code))

Is it possible to align x axis title to a value of the axis?

Having a tibble and a simple scatterplot:
p <- tibble(
x = rnorm(50, 1),
y = rnorm(50, 10)
)
ggplot(p, aes(x, y)) + geom_point()
I get something like this:
I would like to align (center, left, right, as the case may be) the title of the x-axis - here rather blandly x - with a specific value on the axis, say the off-center 0 in this case. Is there a way to do that declaratively, without having to resort to the dumb (as in "free of context") trial-and-error element_text(hjust=??). The ?? are rather appropriate here because every value is a result of experimentation (my screen and PDF export in RStudio never agree on quite some plot elements). Any change in the data or the dimensions of the rendering may (or may not) invalidate the hjust value and I am looking for a solution that graciously repositions itself, much like the axes do.
Following the suggestions in the comments by #tjebo I dug a little deeper into the coordinate spaces. hjust = 0.0 and hjust = 1.0 clearly align the label with the Cartesian coordinate system extent (but magically left-aligned and right-aligned, respectively) so when I set specific limits, calculation of the exact value of hjust is straightforward (aiming for 0 and hjust = (0 - -1.5) / (3.5 - -1.5) = 0.3):
ggplot(p, aes(x, y)) +
geom_point() +
coord_cartesian(ylim = c(8, 12.5), xlim = c(-1.5, 3.5), expand=FALSE) +
theme(axis.title.x = element_text(hjust = 0.3))
This gives an acceptable result for a label like x, but for longer labels the alignment is off again:
ggplot(p %>% mutate(`Longer X label` = x), aes(x = `Longer X label`, y = y)) +
geom_point() +
coord_cartesian(ylim = c(8, 12.5), xlim = c(-1.5, 3.5), expand=FALSE) +
theme(axis.title.x = element_text(hjust = 0.3))
Any further suggestions much appreciated.
Another option (different enough hopefully to justify the second answer) is as already mentioned to create the annotation as a separate plot. This removes the range problem. I like {patchwork} for this.
library(tidyverse)
library(patchwork)
p <- tibble( x = rnorm(50, 1), y = rnorm(50, 10))
p1 <- tibble( x = rnorm(50, 1), y = 100*rnorm(50, 10))
## I like to define constants outside my ggplot call
mylab <- "longer_label"
x_demo <- c(-1, 2)
demo_fct <- function(p){
p1 <- ggplot(p, aes(x, y)) +
geom_point() +
labs(x = NULL) +
theme(plot.margin = margin())
p2 <- ggplot(p, aes(x, y)) +
## you need that for your correct alignment with the first plot
geom_blank() +
annotate(geom = "text", x = x_demo, y = 1,
label = mylab, hjust = 0) +
theme_void() +
# you need that for those annoying margin reasons
coord_cartesian(clip = "off")
p1 / p2 + plot_layout(heights = c(1, .05))
}
demo_fct(p) + plot_annotation(title = "demo1 with x at -1 and 2")
demo_fct(p1) + plot_annotation(title = "demo2 with larger data range")
Created on 2021-12-04 by the reprex package (v2.0.1)
I still think you will fair better and easier with custom annotation. There are typically two ways to do that. Either direct labelling with a text layer (for single labels I prefer annotate(geom = "text"), or you create a separate plot and stitch both together, e.g. with patchwork.
The biggest challenge is the positioning in y dimension. For this I typically take a semi-automatic approach where I only need to define one constant, and set the coordinates relative to the data range, so changes in range should in theory not matter much. (they still do a bit, because the panel dimensions also change). Below showing examples of exact label positioning for two different data ranges (using the same constant for both)
library(tidyverse)
# I only need patchwork for demo purpose, it is not required for the answer
library(patchwork)
p <- tibble( x = rnorm(50, 1), y = rnorm(50, 10))
p1 <- tibble( x = rnorm(50, 1), y = 100*rnorm(50, 10))
## I like to define constants outside my ggplot call
y_fac <- .1
mylab <- "longer_label"
x_demo <- c(-1, 2)
demo_fct <- function(df, x) {map(x_demo,~{
## I like to define constants outside my ggplot call
ylims <- range(df$y)
ggplot(df, aes(x, y)) +
geom_point() +
## set hjust = 0 for full positioning control
annotate(geom = "text", x = ., y = min(ylims) - y_fac*mean(ylims),
label = mylab, hjust = 0) +
coord_cartesian(ylim = ylims, clip = "off") +
theme(plot.margin = margin(b = .5, unit = "in")) +
labs(x = NULL)
})
}
demo_fct(p, x_demo) %>% wrap_plots() + plot_annotation(title = "demo 1, label at x = -1 and x = 2")
demo_fct(p1, x_demo) %>% wrap_plots() + plot_annotation(title = "demo 2 - different data range")
Created on 2021-12-04 by the reprex package (v2.0.1)

Ggplot2 axis label from column name of apply function iteration

I would like to change the y axis label (or main title would also be fine) of a ggplot to reflect the column name being iterated over within an apply function.
Here is some sample data and my working apply function:
trial_df <- data.frame("Patient" = c(1,1,2,2,3,3,4,4),
"Outcome" = c("NED", "NED", "NED", "NED", "Relapse","Relapse","Relapse","Relapse"),
"Time_Point" = c("Baseline", "Week3", "Baseline", "Week3","Baseline", "Week3","Baseline", "Week3"),
"CD4_Param" = c(50.8,53.1,20.3,18.1,30.8,24.5,35.2,31.0),
"CD8_Param" = c(5.3,9.7,4.4,4.3,3.1,3.2,5.6,5.3),
"CD3_Param" = c(11.6,16.6,5.0,5.1,14.3,7.1,5.9,8.1))
apply(trial_df[,4:length(trial_df)], 2, function(i) ggplot(data = trial_df, aes_string(x = "Time_Point", y = i )) +
facet_wrap(~Outcome) +
geom_boxplot(alpha = 0.1) +
geom_point(aes(color = `Outcome`, fill = `Outcome`)) +
geom_path(aes(group = `Patient`, color = `Outcome`)) +
theme_minimal() +
ggpubr::stat_compare_means( method = "wilcox.test") +
scale_fill_manual(values=c("blue", "red")) +
scale_color_manual(values=c("blue", "red")))
Example plot output
This creates 3 graphs as expected, however the y axis just says "y". I would like this to display the column name for the column in that iteration. It would also be fine to add a main title with this information, as I just need to know which graph corresponds to which column.
Here are things I have already tried adding to the ggplot code above based on some similar questions I found, but all of them give me the error "non-numeric argument to binary operator":
ggtitle(paste(i))
labs(y = i)
labs(y = as.character(i))
Any help or resources I may have missed would be greatly appreciated, thanks!
So.....for the strangest of reasons I cannot figure out why. This gives what you want but for only one graph!!!
apply(trial_df[,4:length(trial_df)], 2, function(i) ggplot(data = trial_df, aes_string(x = "Time_Point", y = i )) +
facet_wrap(~Outcome) +
geom_boxplot(alpha = 0.1) +
geom_point(aes(color = `Outcome`, fill = `Outcome`)) +
geom_path(aes(group = `Patient`, color = `Outcome`)) +
theme_minimal() +
stat_compare_means( method = "wilcox.test") +
scale_fill_manual(values=c("blue", "red")) +
scale_color_manual(values=c("blue", "red"))+
labs(y=colnames(trial_df)[i]))
Gives these:

ggplot2: axis does not show all ticks/breaks

I am currently plotting data using the ggpubr package in R (based on ggplot2). When I plot the means of two conditions including standard errors, the y-axis should be limited from 1 to 7, which I indicate using:
p <- ggline(data, x = "condition", y = "measure",
add = c("mean_se"),
ylab = "Measure")
ggpar(y, ylim = c(1, 7), ticks=T, yticks.by = 1)
In the final plot, however, the y-axis shows only values from 1 to 6
I tried to plot the same data using native ggplot2, but the problem persists, once I change the layout.
For ggplot2 I used:
p <- ggplot(data, aes(x=condition, y=measure)) +
geom_line() +
geom_point()+
geom_errorbar(aes(ymin=measure-se, ymax=measure+se), width=.2, position=position_dodge(0.05)) +
ylab("measure") +
xlab("Condition")
p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
p + theme_classic()
It would be great if someone could help me with this issue.
Edit:
as suggested in the comments, here is the data I am trying to plot using ggplot2:
structure(list(condition = structure(3:4, .Label = c("IC", "SC",
"ILC", "SLC"), class = "factor"), measure = c(4.10233918128655, 3.83040935672515
), se = c(0.235026318386523, 0.216811675834834)), class = "data.frame", row.names = c(NA,
-2L))
I think I got something resembling your plot with correct y-axes with the following code:
ggplot(data, aes(x = condition, y = measure)) +
geom_point() +
geom_errorbar(aes(ymin = measure-se, ymax = measure+se),
width = .2, position = position_dodge(0.05)) +
# Group prevents geom_line interpreting each x-axis point as it's own group
geom_line(aes(group = rep(1, nrow(data)))) +
xlab("Condition") +
# Expand is optional, it prevents padding beyond 1 and 7
scale_y_continuous(name = "measure",
limits = c(1, 7),
breaks = 1:7,
expand = c(0,0)) +
theme_classic()
The solution is much more trivial. You were doing everything right! Except for one clerical error. Here is what was happening:
First, you generate your initial plot, fine.
p <- ggplot(data, aes(x=condition, y=measure)) +
geom_line() + geom_point() +
geom_errorbar(aes(ymin=measure-se, ymax=measure+se),
width=.2, position=position_dodge(0.05)) +
ylab("measure") +
xlab("Condition")
This plot does not have the limits. When you add the limits and display it, the scales are correct:
p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
However, note that p did not change! You did not store the result of adding the limits to p. Therefore, p is still without the scale_y_continuous. No wonder then that when you type
p + theme_classic()
...the limits are gone. However, if you try
p <- p + scale_y_continuous(name="measure", limits=c(1, 7), breaks=c(1:7))
p + theme_classic()
everything will be correct.

Need help on customizing my Odds Ratio (ggplot)!

I'm assigned to create an Odds of Ratio ggplot in R. The plot I'm supposed to create is given below.
Given plot
My job is to figure out codes which creates the exact plots in R. I've done most parts. Here is my work.
My work
Before jumping into my code, it is very important that I am not using the correct values for boxOdds, boxCILow, and boxCIHigh since I have not figured out the correct values. I wanted to figure out codes for ggplot first so I can enter the right values as soon as I find them.
This is the code I used:
library(ggplot2)
boxLabels = c("Females/Males", "Student-Centered Prac. (+1)", "Instructor Quality (+1)", "Undecided / STM",
"non-STEM / STM", "Pre-med / STM", "Engineering / STM", "Std. test percentile (+10)",
"No previous calc / HS calc", "College calc / HS calc")
df <- data.frame(yAxis = length(boxLabels):1,
boxOdds =
c(2.23189, 1.315737, 1.22866, 0.8197413, 0.9802449, 0.9786673, 0.6559005, 0.5929812, 0.6923759, 1.3958275),
boxCILow =
c(.7543566,1.016,.9674772,.6463458,.9643047,.864922,.4965308,.3572142, 0.4523759, 1.2023275),
boxCIHigh =
c(6.603418,1.703902,1.560353,1.039654,.9964486,1.107371,.8664225,.9843584, 0.9323759, 1.5893275)
)
(p <- ggplot(df, aes(x = boxOdds, y = boxLabels)) +
geom_vline(aes(xintercept = 1), size = 0.75, linetype = 'dashed') +
geom_errorbarh(aes(xmax = boxCIHigh, xmin = boxCILow), size = .5, height =
0, color = 'gray50') +
geom_point(size = 3.5, color = 'orange') +
theme_bw() +
theme(panel.grid.minor = element_blank()) +
scale_x_continuous(breaks = seq(0,7,1) ) +
ylab('') +
xlab('Odds Ratio') +
annotate(geom = 'text', y =1.1, x = 3.5, label ='',
size = 3.5, hjust = 0) + ggtitle('Estimated Odds of Switching') +
theme(plot.title = element_text(hjust = 0.5, size = 30),
axis.title.x = (element_text(size = 15))) +
theme(panel.grid.minor = element_blank(), panel.grid.major = element_blank())
)
p
Where I'm stuck at:
Removing small vertical lines on the beginning and end of each row's CI). I was not sure what it's called so I was having hard time looking it up. SOLVED
I'm also stuck at coloring specific rows in different colors.
The last part I'm stuck at is assigning proper order of each variable for y-axis. As you can see in my code ("boxLabels" part), I have put all the variables in order of given plot but it seems like the R didn't care about the order. So the varaible located at the very top is "Undecided / STM", instead of "Females / Males".
How do I decrease the space from 0 to 1? SOLVED
Any help would be appreciated!
First, probably you want ggstance::geom_pointrangeh. Second, you could define colors by yAxis right at the beginning. To group some factors create a new variable group. Third is related to your data where you could assign factor labels. Fourth, remove coord_trans as suggested by #beetroot.
Assign factor labels
dat$yAxis <- factor(dat$yAxis, levels=10:1, labels=rev(boxLabels))
Create groups
dat$group <- 1
dat$group[which(dat$yAxis %in% c("Females/Males", "Undecided / STM", "non-STEM / STM",
"Pre-med / STM"))] <- 2
dat$group[which(dat$yAxis %in% c("Student-Centered Prac. (+1)",
"No previous calc / HS calc",
"College calc / HS calc"))] <- 3
Colors
colors <- c("#860fc2", "#fc691d", "black")
Plot
library(ggplot2)
library(ggstance)
ggplot(dat, aes(x=boxOdds, y=yAxis, color=as.factor(group))) +
geom_vline(aes(xintercept=1), size=0.75, linetype='dashed') +
geom_pointrangeh(aes(xmax=boxCIHigh, xmin=boxCILow), size=.5,
show.legend=FALSE) +
geom_point(size=3.5, show.legend=FALSE) +
theme_bw() +
scale_color_manual(values=colors)+
theme(panel.grid.minor=element_blank()) +
scale_x_continuous(breaks=seq(0,7,1), limits=c(0, max(dat[2:4]))) +
ylab('') +
xlab('Odds Ratio') +
annotate(geom='text', y =1.1, x=3.5, label ='',
size=3.5, hjust=0) + ggtitle('Estimated Odds of Switching') +
theme(plot.title=element_text(hjust=.5, size=20)) +
theme(panel.grid.minor=element_blank(), panel.grid.major=element_blank())
Gives
Data
dat <- structure(list(yAxis = 10:1, boxOdds = c(2.23189, 1.315737, 1.22866,
0.8197413, 0.9802449, 0.9786673, 0.6559005, 0.5929812, 0.6923759,
1.3958275), boxCILow = c(0.7543566, 1.016, 0.9674772, 0.6463458,
0.9643047, 0.864922, 0.4965308, 0.3572142, 0.4523759, 1.2023275
), boxCIHigh = c(6.603418, 1.703902, 1.560353, 1.039654, 0.9964486,
1.107371, 0.8664225, 0.9843584, 0.9323759, 1.5893275)), class = "data.frame", row.names = c(NA,
-10L))

Resources