Rearranging trendline colors in ggplot - r

I created a plot that turned out mostly how I'd like it in ggplot but I need the lines to appear in a slightly different color arrangement.
Basically, I need all "mean" lines to appear in blue and all "odd" lines to appear in red. Pref 1 will appear in either the lighter or darker shade and vice versa. As you can see ggplot has not quite done that.
p2 <- ggplot(asd_pref_plot_groups, aes(x, pref_plot_groups$predicted, col = combined)) +
geom_line(size=1.5) +
scale_color_manual(values = c("blue","deepskyblue","red","pink")) +
geom_ribbon(aes(ymin=conf.low,ymax=conf.high, fill=combined),alpha=.2,colour=NA) +
scale_fill_manual(values = c("blue","deepskyblue","red","pink")) +
geom_point(data=summStats,aes(trial,mean,col = combined),size=2) +
scale_color_manual(values = c("blue","deepskyblue","red","pink")) +
theme_bw() +
xlab('Trial') +
ylab('Prediction Error') +
ggtitle('ASD learning about TD vs. ASD \n learning about ASD') +
theme(text=element_text(size=20),
plot.title = element_text(hjust = 0.5),
panel.border = element_blank())
Above is my code. I thought I could shift around scale_color_manual as needed but it doesn't seem to work? Is there an easy fix or does this extend to my data frames. Thank you

Your question didn't include any example data, so I have had to try to recreate your data set (see footnote)
To ensure we are on the right track, I will use exactly your plotting code to get a very similar plot:
ggplot(asd_pref_plot_groups, aes(x, pref_plot_groups$predicted, col = combined)) +
geom_line(size=1.5) +
scale_color_manual(values = c("blue","deepskyblue","red","pink")) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high, fill = combined),
alpha = 0.2, colour = NA) +
scale_fill_manual(values = c("blue","deepskyblue","red","pink")) +
geom_point(data = summStats, aes(trial, mean,col = combined), size = 2) +
scale_color_manual(values = c("blue","deepskyblue","red","pink")) +
theme_bw() +
xlab('Trial') +
ylab('Prediction Error') +
ggtitle('ASD learning about TD vs. ASD \n learning about ASD') +
theme(text=element_text(size=20),
plot.title = element_text(hjust = 0.5),
panel.border = element_blank())
All we need to do here is to remove one of your redundant scale_color_manual calls (you currently have 2), and change the ordering of the colors in both the fill and color scales:
ggplot(asd_pref_plot_groups, aes(x, pref_plot_groups$predicted,
col = combined, fill = combined)) +
geom_line(size = 1.5) +
geom_ribbon(aes(ymin = conf.low, ymax = conf.high),
alpha = 0.2, colour = NA) +
scale_fill_manual(values = c("blue","red", "deepskyblue", "pink")) +
scale_color_manual(values = c("blue","red","deepskyblue", "pink")) +
geom_point(data = summStats, aes(trial, mean,col = combined), size = 2) +
theme_bw() +
xlab('Trial') +
ylab('Prediction Error') +
ggtitle('ASD learning about TD vs. ASD \n learning about ASD') +
theme(text=element_text(size=20),
plot.title = element_text(hjust = 0.5),
panel.border = element_blank())
Footnote: Reproducible data to approximate data in question
set.seed(1)
asd_pref_plot_groups <- data.frame(x = rep(c(1, 60), 4),
combined = rep(c('pref1_mean', 'pref1_odd',
'pref2_mean', 'pref2_odd'),
each = 2),
predicted = c(1.3, 1.3, 1.45, 1.3,
2, 1.75, 2.05, 1.77),
conf.high = c(1.35, 1.35, 1.5, 1.35,
2.05, 1.8, 2.1, 1.82),
conf.low = c(1.25, 1.25, 1.4, 1.25,
1.95, 1.7, 2, 1.72))
pref_plot_groups <- asd_pref_plot_groups
summStats <- data.frame(trial = rep(1:60, 4),
combined = rep(c('pref1_mean', 'pref1_odd',
'pref2_mean', 'pref2_odd'),
each = 60),
mean = c(rnorm(60, seq(1.3, 1.3, length = 60), 0.05),
rnorm(60, seq(1.45, 1.3, length = 60), 0.05),
rnorm(60, seq(2, 1.75, length = 60), 0.05),
rnorm(60, seq(2.05, 1.77, length = 60), 0.05)))

Related

how to add manually a legend to ggplot [duplicate]

This question already has an answer here:
ggplot2 add manual legend for two data series
(1 answer)
Closed 2 years ago.
I want to add manually a legend to ggplot in r. The problem of my code is that it does not show the right symbols (blue point, blue dashed line and red solid line). Here the code and the plot.
predict_ID1.4.5.6.7 <- predict(lm_mRNATime, ID1.4.5.6.7)
ID1.4.5.6.7$predicted_mRNA <- predict_ID1.4.5.6.7
colors <- c("data" = "Blue", "predicted_mRNA" = "red","fit"="Blue")
ggplot( data = ID1.4.5.6.7, aes(x=Time,y=mRNA,color="data")) +
geom_point()+
scale_x_discrete(limits=c('0','20','40','60','120'))+
labs(title="ID-1,ID-4,ID-5,ID-6,ID-7",y="mRNA", x="Time [min]", color = "Legend") +
scale_color_manual(values = colors)+
geom_line(aes(x=Time,y=predicted_mRNA,color="predicted_mRNA"),lwd=1.3)+
geom_smooth(method = "lm",aes(color="fit",lty=2),se=TRUE,lty=2)+
scale_color_manual(values = colors)+
theme(plot.title = element_text(hjust = 0.5),plot.subtitle = element_text(hjust = 0.5))
How can I modify the code in order to get the symbols associated to the plot in the legend ?
The hardest part here was recreating your data set for demonstration purposes. It's always better to add a reproducible example. Anyway, the following should be close:
library(ggplot2)
set.seed(123)
ID1.4.5.6.7 <- data.frame(Time = c(rep(1, 3),
rep(c(2, 3, 4, 5), each = 17)),
mRNA = c(rnorm(3, 0.1, 0.25),
rnorm(17, 0, 0.25),
rnorm(17, -0.04, 0.25),
rnorm(17, -0.08, 0.25),
rnorm(17, -0.12, 0.25)))
lm_mRNATime <- lm(mRNA ~ Time, data = ID1.4.5.6.7)
Now we run your code with the addition of a custom colour guide:
predict_ID1.4.5.6.7 <- predict(lm_mRNATime, ID1.4.5.6.7)
ID1.4.5.6.7$predicted_mRNA <- predict_ID1.4.5.6.7
colors <- c("data" = "Blue", "predicted_mRNA" = "red", "fit" = "Blue")
p <- ggplot( data = ID1.4.5.6.7, aes(x = Time, y = mRNA, color = "data")) +
geom_point() +
geom_line(aes(x = Time, y = predicted_mRNA, color = "predicted_mRNA"),
lwd = 1.3) +
geom_smooth(method = "lm", aes(color = "fit", lty = 2),
se = TRUE, lty = 2) +
scale_x_discrete(limits = c('0', '20', '40', '60', '120')) +
scale_color_manual(values = colors) +
labs(title = "ID-1, ID-4, ID-5, ID-6, ID-7",
y = "mRNA", x = "Time [min]", color = "Legend") +
guides(color = guide_legend(
override.aes = list(shape = c(16, NA, NA),
linetype = c(NA, 2, 1)))) +
theme(plot.title = element_text(hjust = 0.5),
plot.subtitle = element_text(hjust = 0.5),
legend.key.width = unit(30, "points"))

annotate ggplot with discrete axis (w/ reproducible example)

I'm struggling to find a straightforward solution to fix my plot. The problem stems down to the discrete nature of the x-axis. I want to annotate the plot with text and segments in order to show statistical results.
1) I want to print the p-value between "Baby" and "Queen" as well as between "Queen" and "Worker", but ggplot only allows to annotate above each label, not between them.
2) Similarly, I want the first two geom_segments to be separated, but ggplot won't let me end the first one at something like "Queen"-0.1 and start the second one at "Queen"+0.1 as it is mixing factors and numbers.
Fully reproducible example below, with issues on line 12, 13 and 18:
data <- data.frame(Group.1 = rep(c("A","B"),3),Group.2 = c("Baby","Baby","Worker","Worker","Queen","Queen"),
value = c(0.18,0.30,0.09,0.25,-0.26,-0.55))
boxplot_candidates <- ggplot(aes(y=value,x=Group.2,fill=Group.2),data= data) + theme_bw() +
scale_fill_manual(values=c("lightgreen","darkgreen","goldenrod1"),name="") +
theme(plot.title = element_text(face="bold", size=18, hjust=0)) +
labs(x="",y="Transcript expression\n(log2-centered TMM-nornalised TPMs)") +
theme(plot.title=element_text(size=18, vjust=2),legend.position="", legend.text=element_text(size=14),
axis.text.x = element_text(size = 14, colour = "black"),
axis.text.y = element_text(size = 14, colour = "black"),
axis.title.y=element_text(size = 14, colour = "black",vjust=1),
axis.title.x=element_text(size = 14, colour = "black")) +
geom_segment(aes(x="Baby",xend="Queen",y=0.7,yend=0.7)) + ##### MAKE XEND SMALLER
geom_segment(aes(x="Queen",xend="Worker",y=0.7,yend=0.7)) + ##### MAKE XEND LARGER
geom_segment(aes(x="Baby",xend="Worker",y=1.2,yend=1.2)) +
ylim(-1.5,1.5) + stat_boxplot(geom ='errorbar') +
geom_boxplot(notch=F,outlier.shape=NA) +
geom_point(size=2,position = position_jitter(width = 0.2)) + stat_summary(fun.y=mean, colour = "white",geom="point", size=4) +
annotate("text", x = as.factor(unique(data$Group.2)),y=c(0.8,0.8,1.3),
label = c("p < 0.001","p < 0.001","p = 0.89"),family="",fontface = 3,size=4) ##### PRINT "p < 0.001" BETWEEN LABELS
print(boxplot_candidates)
Categorical variables are simply placed at locations 1, 2, 3, etc. If you want to reach locations between two categorical variables, you can use coordinates such as 1.2 or 1.5 etc.
Here is a reproducible example with all the irrelevant theme code stripped out:
data <- data.frame(Group.1 = rep(c("A", "B"), 3),
Group.2 = c("Baby", "Baby", "Worker", "Worker", "Queen", "Queen"),
value = c(0.18, 0.30, 0.09, 0.25, -0.26, -0.55))
ggplot(data, aes(y = value, x = Group.2, fill = Group.2)) +
stat_boxplot(geom = 'errorbar') +
geom_boxplot(notch = F, outlier.shape = NA) +
geom_segment(aes(x=1.1, xend=1.9, y=0.7, yend=0.7)) +
geom_segment(aes(x=2.1, xend=2.9, y=0.7, yend=0.7)) +
geom_segment(aes(x=1.1, xend=2.9, y=1.2, yend=1.2)) +
geom_point(size = 2, position = position_jitter(width = 0.2)) +
stat_summary(fun.y = mean, colour = "white", geom = "point", size = 4) +
annotate("text",
x = c(1.5, 2.5, 2),
y = c(0.8, 0.8, 1.3),
label = c("p < 0.001", "p < 0.001", "p = 0.89"),
family = "", fontface = 3, size=4) +
scale_fill_manual(values=c("lightgreen", "darkgreen", "goldenrod1"),
guide = "none") +
ylim(-1.5, 1.5) +
labs(x="", y="Transcript expression\n(log2-centered TMM-nornalised TPMs)") +
theme_bw()

Applying log scale to y-axis for visualizing proportions with ggplot2

I am attempting to recreate some plots from a research article in R and am running into an issue with applying a log scale to y axis. The visualization I'm attempting to recreate is this:
reference plot with y log scale
I currently have a working version without the logarithmic scale applied to the y-axis:
Proportion_Mean_Plot <- ggplot(proportions, aes(days2,
proportion_mean, group = observation)) +
geom_point(aes(shape = observation)) +
geom_line() +
scale_x_continuous(breaks = seq(0,335,20)) +
scale_y_continuous(breaks = seq(0,6,.5)) +
theme_tufte() +
geom_rangeframe() +
theme(legend.position="none") +
theme(axis.line.x = element_line(colour = "black", size = 0.5, linetype = 1),
axis.line.y = element_line(colour = "black", size = 0.5, linetype = 1)) +
labs(title = "Proportion of Baseline Mean",
subtitle = "Daily steps within each intervention phase",
x = "DAYS",
y = "PROPORTION OF BASELINE \n(MEAN)") +
geom_vline(xintercept = 164.5) +
geom_hline(yintercept = 1) +
annotate("text", x = c(82, 246), y = 5,
label = c("Intervention 1", "Intervention 2")) +
geom_segment(aes(x = 0, y = mean, xend = end, yend = mean),
data = proportion_intervention1_data) +
geom_segment(aes(x = start, y = mean, xend = end, yend = mean),
data = proportion_intervention2_data, linetype = 4)
This produces a decent representation of the original:
normally scaled y-axis plot
I would like to try to apply that logarithmic scaling to more closely match it. Any help is appreciated.
As per Richard's suggestion, here is a quick example how you can use scale_y_log10:
suppressPackageStartupMessages(library(tidyverse))
set.seed(123)
# generate some data
proportions <- tibble(interv_1 = pmax(0.4, rnorm(160, mean = 1.3, sd = 0.2)),
interv_2 = pmax(0.01, rnorm(160, mean = 1.6, sd = 0.5)))
proportions <- proportions %>%
gather(key = observation, value = proportion_mean) %>%
mutate(days2 = 1:320)
# create the plot
ggplot(proportions, aes(days2, proportion_mean, group = observation)) +
geom_point(aes(shape = observation)) +
geom_line() +
scale_x_continuous(breaks = seq(0,335,20), expand = c(0, 0)) +
scale_y_log10(breaks = c( 0.1, 0.5, 1, 2, 3, 4, 5), limits = c(0.1, 5)) +
# theme_tufte() +
# geom_rangeframe() +
theme(legend.position="none") +
theme(axis.line.x = element_line(colour = "black", size = 0.5, linetype = 1),
axis.line.y = element_line(colour = "black", size = 0.5, linetype = 1)) +
labs(title = "Proportion of Baseline Mean",
subtitle = "Daily steps within each intervention phase",
x = "DAYS",
y = "PROPORTION OF BASELINE \n(MEAN)") +
geom_vline(xintercept = 164.5) +
geom_hline(yintercept = 1) +
annotate("text", x = c(82, 246), y = 5,
label = c("Intervention 1", "Intervention 2")) +
# plugged the values for the means of the two distributions
geom_segment(aes(x = 0, y = 1.3, xend = 164.5, yend = 1.3)) +
geom_segment(aes(x = 164.5, y = 1.6, xend = 320, yend = 1.6), linetype = 4)

Error with using side-by-side, nudged graphs in ggplot (facet_wrap and position_nudge)

I'm trying to create side-by-side plots with nudged data points (Odds ratios, with 95% CI error bars) in R using ggplot. Each time I try to combine them I get an error. Can anyone help me identify what I should do to change my code? This is the error I get:
Error in (~surv) + scale_x_continuous(breaks = seq(0, 4, 1)) :
non-numeric argument to binary operator
To illustrate what I'm trying to do, see below a version I created using plot(), which you can see is fairly ugly: I've tried combining the facet_wrap and position_nudge based on the guidance in the J Stuart Carlton blog, but haven't been able to add a position_nudge. The error code above suggests that the problem is with facet_wrap section of my code.
I've included code below describing how to replicate my dataset.
activity <- factor(rep(c("Good interaction", "Poor interaction",
"RTW plan"), times = 4))
surv <- factor(rep(c("T1", "T2"), each = 3, times = 2))
mod <- factor(rep(c("Crude", "Adjusted"), each = 6))
or <- c(1.72, 1.26, 2.39, 2.5, 1.34, 1.89, 1.14, 1.09, 2.02, 1.9, 1.1, 1.02)
low <- c(1.22, 0.74, 1.73, 1.74, 0.61, 1.35, 0.77, 0.61, 1.40, 1.22, 0.60, 0.68)
hi <- c(2.41, 2.16, 3.29, 3.6, 1.8, 2.64, 1.70, 1.94, 2.90, 2.95, 2.04, 1.54)
rtwc <- data.frame(activity, surv, mod, or, low, hi)
And here is the ggplot code I've been using:
ggplot(rtwc, aes(x = or, y = activity, colour = mod)) +
geom_vline(aes(xintercept = 1), size = 0.25, linetype = "dashed") +
geom_errorbarh(data = filter(rtwc, mod == "crude"), aes(xmax = hi, xmin = low), size = 0.5, height = 0.1, colour = "gray50", position = position_nudge(y = fix)) +
geom_point(data = filter(rtwc, mod == "crude"), aes(xmax = hi, xmin = low), size = 4, position_nudge(y = fix)) +
geom_errorbarh(data = filter(rtwc, mod == "Adjusted"), aes(xmax = hi, xmin = low), size = 0.5, height = 0.1, colour = "gray50", position = position_nudge(y = -fix)) +
geom_point(data = filter(rtwc, mod == "Adjusted"), size = 4, position = position_nudge(y = -fix)) +
geom_errorbarh(data = filter(rtwc, mod = "Adjusted")) +
facet_wrap = (~surv) +
scale_x_continuous(breaks = seq(0, 4, 1)) +
coord_trans(x = "log10") +
theme_bw() +
theme(panel.grid.minor = element_blank())
Apologies if there is already a post on this question.
Here are some code to get you started. I used position_dodge together with coord_flip to keep the error bar pairs away from each other:
ggplot(rtwc,
aes(y = or, ymin = low, ymax = hi, x = activity, group = mod)) +
geom_hline(yintercept = 1, size = 0.25, linetype = "dashed", colour = "grey") +
geom_errorbar(width = 0.2, position = position_dodge(0.5)) +
geom_point(aes(col = mod), position = position_dodge(0.5),
size = 3) +
scale_x_discrete(name = "") +
scale_y_log10(name = "", breaks = seq(0, 4)) +
scale_color_manual(name = "", values = c("red", "blue")) + # change colours here
expand_limits(y = c(0.1, 4)) + #adjust x axis range here
facet_wrap(~surv) +
coord_flip() +
theme_bw() + #change look & feel here
theme(panel.grid.minor = element_blank())
For tweaks to the plot's look & feel, you can check out the available themes in ggplot here, & more themes in ggthemes here. Just please don't use the Excel 2013 theme. As the creator noted, its presence is for ironic purposes only.
For tweaks to the point colours, here's a handy reference for colours by name. Or you can use one of the palettes from RColorBrewer, viewable via RColorBrewer::display.brewer.all().

ggplot2 v2.21.9 sec.axis in polar plot

I am currently trying to add a secondary axis using the recently introduced function sec.axis in ggplot2. This function works well with scatter/bar plots, but not for polar plot: In the following code, the name for the second y-axis appears, but not the axis.
Is there any workaround or option, that I have not figured out?
require(ggplot2)
set.seed(40);
Location <- data.frame(Winkel = round(runif(1000, 0, 24), 0))
Location$BAD <- Location$Winkel %in% c(seq(7, 18))
Abschnitte <- c(0:24)
polar <- data.frame(Winkel2 = c(1.5, 2.34, 1.2, 3.45, 1.67, 2.61, 1.11, 13.2),
value = c(0.1, 0.03, 0.02, 0.015, 0.01, 0.04, 0.09, 0.06))
ggplot(Location, aes(x = Winkel, fill = BAD, y = (..count..)/sum(..count..))) +
geom_histogram(breaks = seq(0,24), colour = "black") +
coord_polar(start = 0) + theme_minimal() +
scale_fill_brewer(type = "seq", palette = 3) +
ylab("Percentual allocation time") +
ggtitle("") +
scale_x_continuous("", limits = c(0, 24), breaks = Abschnitte, labels = Abschnitte) +
scale_y_continuous(labels = scales::percent,
sec.axis = sec_axis(~.*5, name = "mean direction")) +
geom_segment(data = polar, aes(x = Winkel2, y = 0, xend = Winkel2, yend = value, fill = NA),
arrow = arrow(angle = 30, type = "closed", length = unit(0.3, "cm")))
As #henrik mentioned in the comments, this is a bug. It's been patched and is available if you use the development version from GitHub (i.e., devtools::install_github("tidyverse/ggplot2")).
Here's the example after the patch:
require(ggplot2)
#> Loading required package: ggplot2
set.seed(40);
Location <- data.frame(Winkel = round(runif(1000, 0, 24), 0))
Location$BAD <- Location$Winkel %in% c(seq(7, 18))
Abschnitte <- c(0:24)
polar <- data.frame(Winkel2 = c(1.5, 2.34, 1.2, 3.45, 1.67, 2.61, 1.11, 13.2),
value = c(0.1, 0.03, 0.02, 0.015, 0.01, 0.04, 0.09, 0.06))
ggplot(Location, aes(x = Winkel, fill = BAD, y = (..count..)/sum(..count..))) +
geom_histogram(breaks = seq(0,24), colour = "black") +
coord_polar(start = 0) + theme_minimal() +
scale_fill_brewer(type = "seq", palette = 3) +
ylab("Percentual allocation time") +
ggtitle("") +
scale_x_continuous("", limits = c(0, 24), breaks = Abschnitte, labels = Abschnitte) +
scale_y_continuous(labels = scales::percent,
sec.axis = sec_axis(~.*5, name = "mean direction")) +
geom_segment(data = polar, aes(x = Winkel2, y = 0, xend = Winkel2, yend = value, fill = NA),
arrow = arrow(angle = 30, type = "closed", length = unit(0.3, "cm")))
#> Warning: Ignoring unknown aesthetics: fill

Resources