This question already has answers here:
Change stacked bar order when aesthetic fill is based on the interaction of two factors
(1 answer)
ggplot legends - change labels, order and title
(1 answer)
Closed 2 years ago.
Currently, I have a plot that looks like this:
library(ggplot2)
df <- ToothGrowth
df %>%
ggplot(aes(x = supp, y = len, fill = supp)) +
geom_flat_violin(position = position_nudge(x = .2, y = 0),
alpha = .8) +
geom_point(aes(shape = supp),
position = position_jitter(width = .05),
size = 2, alpha = 0.8) +
geom_boxplot(width = .1, outlier.shape = NA, alpha = 0.5) +
coord_flip() +
labs(title = "ToothGrowth Length by Supplement",
y = "Length") +
theme_classic() +
raincloud_theme
I'd like to change the order so that OJ appears above VC. I've tried adding scale_x_discrete before coord_flip(), but that seems to mess up my plot as this is a raincloud plot -- I'd have to move not only the violin plot, but also the points and the box plot. I've also tried adding rev(), which also messed up my plot. What is the best way to reorder this?
EDIT
Thank you for the comment! How do I change the orders in an interaction plot?
df %>%
mutate(Supplement = ifelse(supp == "VC",
"VC",
"OJ"),
Dose = ifelse(dose == "0.5",
"0.5",
"1.0"),
Interaction = factor(str_replace(interaction(Supplement, Dose),
'\\.', '\n'),
ordered=TRUE)) %>%
ggplot(aes(x = Interaction, y = len, fill = Interaction)) +
geom_flat_violin(position = position_nudge(x = .2, y = 0),
alpha = .8) +
geom_point(aes(shape = Dose),
position = position_jitter(width = .05),
size = 2, alpha = 0.8) +
geom_boxplot(width = .1, outlier.shape = NA, alpha = 0.5) +
coord_flip() +
labs(title = "Effect of Supplement and Dose on Length",
y = "Growth Length") +
scale_fill_discrete(guide = guide_legend(override.aes = list(shape = c(".", ".")))) +
scale_shape_discrete(guide = guide_legend(override.aes = list(size = 3))) +
theme_classic() +
raincloud_theme
ggplot2 will interpret the supp factor and the order in the plot correspond to the levels of the factor.
You will need to change the levels of the supp factor.
df <- ToothGrowth
df$supp
df$supp <- relevel(ToothGrowth$supp,ref = "VC")
df$supp
df %>%
ggplot(aes(x = supp, y = len, fill = supp)) +
geom_flat_violin(position = position_nudge(x = .2, y = 0),
alpha = .8) +
geom_point(aes(shape = supp),
position = position_jitter(width = .05),
size = 2, alpha = 0.8) +
geom_boxplot(width = .1, outlier.shape = NA, alpha = 0.5) +
coord_flip() +
labs(title = "ToothGrowth Length by Supplement",
y = "Length") +
theme_classic() +
raincloud_theme
I'm new to R and I've scripted the interaction plot below, for which I want two dotted lines connecting both "coral" and both "darkgoldenrod2" points respectively:
df <- tibble::tribble(~Proportion, ~Lower,~Upper, ~Area,~Time,
invlogit(-0.033886), invlogit(-0.517223067), invlogit(0.449451067), "SNP", "Day",
(invlogit(-0.9231219)+invlogit(-0.3786)), 0.5727 ,0.8087, "SNP", "Night",
invlogit(-0.9231219), invlogit(-1.406458967), invlogit(-0.439784833),"LGCA", "Day",
invlogit(-0.1604356), invlogit(-0.643772667) ,invlogit(0.322901467), "LGCA","Night")
df
dfnew <- df %>%
mutate(ymin = Proportion - Lower,
ymax = Proportion + Upper)
p <- ggplot(data = dfnew, aes(x = Time, y = Proportion, color=Area)) +
geom_point(size = 6, stroke = 0, shape = 16,
position = position_dodge(width = 0.1))+
geom_errorbar(aes(y=Proportion, ymin = Lower, ymax = Upper),width=0.1,size=1,
position = position_dodge(width = 0.1)) +
theme(axis.text=element_text(size=15),
axis.title=element_text(size=20)) +
scale_color_manual(values = c("SNP" = "coral",
"LGCA" = "darkgoldenrod2"))
p
Reading other posts here on SO, I've used the command line: +geom_line(aes(group = 1),size=2)
This however isn't producing the desired plot as you can see below:
Any help with this is truly appreciated!
You should add group=Area to your ggplot mapping and then you just need to call geom_line. You also don't need y=Position in geom_errorbar.
p <- ggplot(data = dfnew, aes(x = Time, y = Proportion, color=Area, group=Area)) +
geom_point(size = 6, stroke = 0, shape = 16,
position = position_dodge(width = 0.1))+
geom_errorbar(aes(ymin = Lower, ymax = Upper), width=0.1, size=1,
position = position_dodge(width = 0.1)) +
theme(axis.text=element_text(size=15),
axis.title=element_text(size=20)) +
scale_color_manual(values = c("SNP" = "coral",
"LGCA" = "darkgoldenrod2")) +
geom_line(size=2)
p
I am try to do a plot whith means lines by group (in ggplot), and i have my code like this
ggplot(gama, aes(x = distancia, y= glipidoscmtejido, colour= estado)) +
geom_point(position=position_dodge(.5), alpha= 1, size=3) +
geom_crossbar(data=gama,aes(x=distancia,ymin=mean(glipidoscmtejido),
ymax=mean(glipidoscmtejido),y=mean(glipidoscmtejido),colour=estado), width = 0.5)
and I get this
but i need the mean line by distancia and by estado. how can i make it?
thanks.
How about this using stat_summary to plot the means per estado per distancia:
# Generate some sample data
set.seed(2017);
df <- cbind.data.frame(
x = rnorm(100),
estado = sample(c("sana", "lesionada"), 100, replace = T),
distancia = sample(c("0-1", "2.5-3.5", "5.6"), 100, replace = T));
require(ggplot2);
ggplot(df, aes(x = distancia, y = x, colour = estado)) +
geom_point(position = position_dodge(width = 0.3)) +
stat_summary(
fun.y = mean,
geom = "errorbar",
aes(ymax = ..y.., ymin = ..y..),
position = position_dodge(width = 0.3),
width = 0.25);
I wanted to comment on the following doubt.
Using this code:
Plot<-data.frame(Age=c(0,0,0,0,0),Density=c(0,0,0,0,0),Sensitivity=c(0,0,0,0,0),inf=c(0,0,0,0,0),sup=c(0,0,0,0,0),tde=c(0,0,0,0,0))
Plot[1,]<-c(1,1,0.857,0.793,0.904,0.00209834)
Plot[2,]<-c(1,2,0.771 ,0.74,0.799,0.00348286)
Plot[3,]<-c(1,3,0.763 ,0.717,0.804,0.00577784)
Plot[4,]<-c(1,4,0.724 ,0.653,0.785,0.00504161)
Plot[5,]<-c(2,1,0.906,0.866,0.934,0.00365742)
Plot[6,]<-c(2,2,0.785 ,0.754,0.813,0.00440399)
Plot[7,]<-c(2,3,0.660,0.593,0.722,0.00542849)
Plot[8,]<-c(2,4,0.544,0.425,0.658,0.00433052)
names(Plot)<-c("Age","Mammographyc density","Sensitivity","inf","sup","tde")
Plot$Age<-c("50-59","50-59","50-59","50-59","60-69","60-69","60-69","60-69")
Plot$Density<-c("Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense","Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense")
levels(Plot$Age)<-c("50-59","60-69")
levels(Plot$Density)<-c("Almost entirely fat","Scattered fibroglandular density","Heterogeneously dense","Extremely dense")
pd <- position_dodge(0.2) #
Plot$Density <- reorder(Plot$Density, 1-Plot$Sensitivity)
ggplot(Plot, aes(x = Density, y = 100*Sensitivity, colour=Age)) +
geom_errorbar(aes(ymin = 100*inf, ymax = 100*sup), width = .1, position = pd) +
geom_line(position = pd, aes(group = Age), linetype = c("dashed")) +
geom_point(position = pd, size = 4)+
scale_y_continuous(expand = c(0, 0),name = 'Sensitivity (%)',sec.axis = sec_axis(~./5, name = 'Breast cancer detection rate (per 1000 mammograms)', breaks = c(0,5,10,15,20),
labels = c('0‰',"5‰", '10‰', '15‰', '20‰')), limits = c(0,100)) +
geom_line(position = pd, aes(x = Density, y = tde * 5000, colour = Age, group = Age), linetype = c("dashed"), data = Plot) +
geom_point(shape=18,aes(x = Density, y = tde * 5000, colour = Age, group = Age), position = pd, size = 4) +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
theme(legend.position="bottom") + guides(colour = guide_legend(), size = guide_legend(),
shape = guide_legend())
I have made the following graph,
in which the axis on the left is the scale of the circles and the axis on the right is the scale of the diamonds. The fact is that I would like to have a legend approximately like this:
But it is impossible for me, I have tried suggestions of other threads like scale_shape and different commands in guides but I have not got success. I just want to make clear the difference in what shape and color represent.
Would someone know how to help me?
Best regards,
What you should do is a panel plot to avoid the confusion of double axes:
library(dplyr)
library(tidyr)
Plot %>%
gather(measure, Result, Sensitivity, tde) %>%
ggplot(aes(x = Density, y = Result, colour=Age)) +
geom_errorbar(aes(ymin = inf, ymax = sup), width = .1, position = pd,
data = . %>% filter(measure == "Sensitivity")) +
geom_line(aes(group = Age), position = pd, linetype = "dashed") +
geom_point(position = pd, size = 4)+
# scale_y_continuous(expand = c(0, 0), limits = c(0, 1)) +
scale_y_continuous(labels = scales::percent) +
facet_wrap(~measure, ncol = 1, scales = "free_y") +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
theme(legend.position="bottom")
But to do what you asked, you problem is that you have only 1 non-positional aesthetic mapped so you cannot get more than one legend. To force a second legend, you need to add a second mapping. It can be a dummy mapping that has no effect, as below we map alpha but then manually scale both levels to 100%. This solution is not advisable because, as you have done in your example of a desired legend, it is easy to mix up the mappings and have your viz tell a lie by mislabeling which points are sensitivity and which are detection rate.
ggplot(Plot, aes(x = Density, y = 100*Sensitivity, colour=Age, alpha = Age)) +
geom_errorbar(aes(ymin = 100*inf, ymax = 100*sup), width = .1, position = pd) +
geom_line(position = pd, aes(group = Age), linetype = c("dashed")) +
geom_point(position = pd, size = 4)+
scale_y_continuous(expand = c(0, 0),name = 'Sensitivity (%)',sec.axis = sec_axis(~./5, name = 'Breast cancer detection rate (per 1000 mammograms)', breaks = c(0,5,10,15,20),
labels = c('0‰',"5‰", '10‰', '15‰', '20‰')), limits = c(0,100)) +
geom_line(position = pd, aes(x = Density, y = tde * 5000, colour = Age, group = Age), linetype = c("dashed"), data = Plot) +
geom_point(shape=18,aes(x = Density, y = tde * 5000, colour = Age, group = Age), position = pd, size = 4) +
theme_light() +
scale_color_manual(name="Age (years)",values = c("50-59"= "grey55", "60-69" = "grey15")) +
scale_alpha_manual(values = c(1, 1)) +
guides(alpha = guide_legend("Sensitivity"),
color = guide_legend("Detection Rate", override.aes = list(shape = 18))) +
theme(legend.position="bottom")
I am having trouble with geom_errorbars particularly in utilizing position_dodge() effectively in this script.
library(ggplot2)
library(plyr)
Dose <- rep(c(3,10,30,100), each = 6)
Visit <- rep(c(1,28), each = 3, times = 4)
Animal <- rep(1:3, times = 8)
Estimate <- runif(24)
Dose <- factor(Dose)
Visit <- factor(Visit)
df <- data.frame(Animal, Dose, Visit, Estimate)
e <- ddply(df, .(Dose, Visit), summarise, mean = mean(Estimate), sd = sd(Estimate), n = length(Estimate))
e$se = e$sd/sqrt(e$n)
trace.out <- ggplot(data = e, aes(x = Visit, y = mean, colour = Dose))
trace.out <- trace.out +
geom_point(data = e, aes(y = mean), size = 3, postion = position_dodge(width = 0.2)) +
geom_line(data = e, aes(y = mean, group = Dose), position = position_dodge(width = 0.2)) +
geom_errorbar(aes(ymin= mean - se, ymax = mean + se), postion = position_dodge(0.2), colour='black', width= 0.3) +
labs(y = 'Estimate') +
theme_bw()
print(trace.out)
The output for me looks like:
I would like for the points, lines and error bars to line up and to have the errorbars not overlap. Is there some way to do that? Additionally I get an error of:
ymax not defined: adjusting position using y instead
Would this have anything to do with it? Thanks in Advance!
Maybe facets are an option:
trace.out <- ggplot(data = e, aes(x = Visit, y = mean, colour = Dose, ymin= mean - se, ymax = mean + se, group = Dose))
trace.out <- trace.out +
geom_point(size = 3, postion = position_dodge(width = 0.2)) +
geom_line(position = position_dodge(width = 0.2), ) +
geom_errorbar(postion = position_dodge(0.2), colour='black', width= 0.3) +
labs(y = 'Estimate') +
theme_bw()
print(trace.out + facet_grid(~Dose) )