I am trying to plot the differences in pairs. I found an example on this forum, but to this graph I would like to add the significance level information using the geom_signif function.
Unfortunately, I get the message back:
"Error in f (...):
Can only handle data with groups that are plotted on the x-axis "
Can someone help me fix this problem?
d <- data.frame(y = rnorm(20, 9, 2),
group = as.factor(rep(c('Post-FAP', 'Post-DEP'), each = 10)),
id = rep(1:10, 2))
ggplot(d, aes(y = y)) +
geom_boxplot(aes(x = rep(c(-2.5, 2.5), each = 10), group = group), fill = '#47E3FF') +
geom_point(aes(x = rep(c(-1, 1), each = 10)), shape = 21, size = 1.5, col = "black", fill = "grey") +
geom_line(aes(x = rep(c(-1, 1), each = 10), group = id)) +
#geom_signif(annotation = "p=0.05", y_position = 13, xmin = -2.5, xmax = 2.5, tip_length = .02) +
scale_x_continuous(breaks = c(-2.5, 2.5), labels = c("Post-FAP", "Post-DEP")) +
scale_y_continuous(minor_breaks = seq(5, 14, by =1),
breaks = seq(6, 14, by = 2), limits = c(5, 14),
guide = "axis_minor") +
theme_bw() +
theme(legend.position = "none", panel.grid = element_blank())
I think what you need to do is install ggh4x. It is an addon to ggplot2 that has some helpful tools, like properly adding ticks and minor ticks in your case. Once you load the R package then you should be good to go.
Edit:
The reason that you were getting that error was that you were not specifying group() for ggsignif
library(ggh4x)
library(ggplot2)
library(ggsignif)
ggplot(d, aes(y = y)) +
geom_boxplot(aes(x = rep(c(-2.5, 2.5), each = 10), group = group), fill = '#47E3FF') +
geom_point(aes(x = rep(c(-1, 1), each = 10)), shape = 21, size = 1.5, col = "black", fill = "grey") +
geom_line(aes(x = rep(c(-1, 1), each = 10), group = id)) +
geom_signif(d, mapping = aes(x=id, y=y,group=group),annotation = "p=0.05", y_position = 13, xmin = -2.5, xmax = 2.5, tip_length = .02) +
scale_x_continuous(breaks = c(-2.5, 2.5), labels = c("Post-FAP", "Post-DEP")) +
scale_y_continuous(minor_breaks = seq(5, 14, by =1),
breaks = seq(5, 14, by = 2), limits = c(5, 14),
guide = "axis_minor") +
theme_bw() +
theme(legend.position = "none", panel.grid = element_blank())
There is a thread here on the error message you posted, saying that all the information on aes (x and y) need to be accessible by the subfunction, i.e. geom_signif.
Using ggplot(d, x=aes(as.numeric(group), y=y, group = group)) worked for me.
Interestingly, ggplot(d, x=aes(rep(c(-2.5, 2.5), each = 10), y=y, group = group)) , did not return an error, but also did not show the geom_signif annotation.
Related
I'm trying to add a legend to my graph which consists of two lines. Unfortunately, I don't understand how. Could you help me out, please? My dataframe can be found below.
Thank you.
# dput(df)
structure(list(t = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), Beta_Treatment = c(0.999550283587599,
1.1284848818908, 1.3173797973744, 1.381630131904, 1.42558575749304,
1.598454651784, 1.68182321476, 1.908913645904, 1.9830406566956,
2.0704834391088), Beta_Control = c(0.822042496772398, 0.914170557749195,
0.812776816705598, 0.829879870335997, 0.906381000106958, 0.891107911295998,
0.885094437239998, 0.810487561695997, 0.816917509704399, 0.881900118891192
), treatment_stderr = c(0.0466078055173255, 0.0451188571313495,
0.0473857585047991, 0.0465872903741648, 0.0436607368165115, 0.0479028140228299,
0.0445418661900949, 0.0451947124622918, 0.0474264037378467, 0.0464878615840165
), control_stderr = c(0.0329566953375247, 0.0319038498369643,
0.0335067911704116, 0.0329421889406788, 0.0308728030745565, 0.0338724046334612,
0.03149585562972, 0.0319574876558628, 0.0335355316903225, 0.0328718821689198
)), class = "data.frame", row.names = c(NA, -10L))
#create and save graph as pdf
p1 <- ggplot(data=df, mapping=aes(y=Beta_Treatment, x=t)) +
geom_line(linetype="dashed", colour = "blue") +
geom_point(shape = 15) +
geom_errorbar(aes(ymin=(Beta_Treatment-1.96*treatment_stderr), ymax=(Beta_Treatment+1.96*treatment_stderr)), width=1) +
ylim(c(0,2.5)) + labs(y = "Beta") +
geom_vline(xintercept = 6) +
scale_x_continuous(limits = c(0, 11), breaks = c(0, 2, 4, 6, 8, 10)) +
theme_bw()
ggsave(last_plot(),filename = "plot.pdf")
p2 <- p1 + geom_line(aes(y=Beta_Control, x=t),linetype="dashed", colour = "green")+
geom_point(aes(y=Beta_Control, x=t), shape = 19) +
geom_errorbar(aes(ymin=(Beta_Control-1.96*control_stderr), ymax=(Beta_Control+1.96*control_stderr )), width=1) +
ylim(c(0,2.5)) +
geom_vline(xintercept = 6) +
theme_bw()
ggsave(last_plot(),filename = "plot2.pdf")
If you want a legend then you have to map on aesthetics, i.e. move color inside aes() and you will automatically get a legend. However, to set your desired colors in that case requires to set them via scale_color_manual.
To this end I map some "speaking" category labels on the color aes and assign colors and labels to these categories inside scale_color_manual. Additionally I used the limits argument to set the order of the categories:
ggplot(data = df, mapping = aes(y = Beta_Treatment, x = t)) +
geom_line(aes(colour = "treat"), linetype = "dashed") +
geom_point(shape = 15) +
geom_errorbar(aes(ymin = (Beta_Treatment - 1.96 * treatment_stderr),
ymax = (Beta_Treatment + 1.96 * treatment_stderr)), width = 1) +
ylim(c(0, 2.5)) +
labs(y = "Beta", color = NULL) +
geom_vline(xintercept = 6) +
scale_x_continuous(limits = c(0, 11), breaks = c(0, 2, 4, 6, 8, 10)) +
theme_bw() +
geom_line(aes(y = Beta_Control, color = "control"), linetype = "dashed") +
geom_point(aes(y = Beta_Control), shape = 19) +
geom_errorbar(aes(ymin = (Beta_Control - 1.96 * control_stderr),
ymax = (Beta_Control + 1.96 * control_stderr)), width = 1) +
scale_color_manual(values = c(treat = "blue", control = "green"),
labels = c(treat = "Treatment", control = "Control"),
limits = c("treat", "control"))
I was able to replicate another good answers here to create a basic radial plot, but can anyone give me any clue of others functions/parameters/ideas on how to convert the basic one to something similar to this :
You could get pretty close like this:
df <- data.frame(x = c(10, 12.5, 15), y = c(1:3),
col = c("#fcfbfc", "#fbc3a0", "#ec6f4a"))
library(ggplot2)
ggplot(df, aes(x = 0, xend = x, y = y, yend = y, color = col)) +
geom_hline(yintercept = c(1:3), size = 14, color = "#dfdfdf") +
geom_hline(yintercept = c(1:3), size = 13, color = "#f7f7f7") +
geom_segment(color = "#bf2c23", size = 14, lineend = 'round') +
geom_segment(size = 13, lineend = 'round') +
scale_color_identity() +
geom_point(aes(x = x - 0.03 * y), size = 5, color = "#bf2c23",
shape = 21, fill = 'white') +
geom_point(aes(x = x - 0.03 * y), size = 2, color = "#bf2c23",
shape = 21, fill = 'white') +
scale_y_continuous(limits = c(0, 4)) +
scale_x_continuous(limits = c(0, 20)) +
coord_polar() +
theme_void()
Here's a start. Are there particular aspects you're trying to replicate? This is a fairly customized format.
df <- data.frame(type = c("on", "ia", "n"),
radius = c(2,3,4),
value = c(10,21,22))
library(ggplot2); library(ggforce)
ggplot(df) +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value),
size = 17, lineend = "round", color = "#bb353c") +
geom_link(aes(x = radius, xend = radius,
y = 0, yend = value, color = type),
size = 16, lineend = "round") +
geom_label(aes(radius, y = 30,
label = paste(type, ": ", value)), hjust = 1.8) +
scale_x_continuous(limits = c(0,4)) +
scale_y_continuous(limits = c(0, 30)) +
scale_color_manual(values = c("on" = "#fff7f2",
"ia" = "#f8b68f",
"n" = "#e4593a")) +
guides(color = "none") +
coord_polar(theta = "y") +
theme_void()
I am trying to align significance asterisks (* or ** or ***) to the points of a geom point graph with position dodge to indicate the significance of a value using ggplot2. I wasn't able to find any similar questions and answers with similar issue.
Here is data frame 'df':
df<-data.frame(conc=c(1,10,100,1, 10,100,1, 10, 100),
mean=c( 0.9008428,0.8278645,0.7890388,0.9541905,
0.8537885,0.8212504,1.3828724,0.7165685, 0.7985398),
Treatment=c("A","A","A","B", "B", "B","C","C", "C"),
upper =c(1.0990144, 0.9505348, 0.8273494, 1.0389074, 0.9227461, 0.9657371, 1.6864420, 0.7401891, 0.9046951),
lower=c(0.7026713, 0.7051941, 0.7507282, 0.9528077, 0.7848309, 0.6767638, 1.0793029, 0.6929479, 0.6923846),
p.value=c(0.0003, 0.6500, 1,0.02,0.0400,
0.3301,0.100,0.023, 0.05))
I made a plot with an automatic asterisk, but it is not aligned how i want to, and i believe it's because of position_dodge, but i have too many points in one concentration, so i have to use it (given data frame is minimal).
legend_title <- "Treatment"
breaks_y =c(0, 0.25, 0.5, 0.75, 1, 1.25, 1.5)
breaks = c(1, 10, 100)
df$Label <- NA
df$Label[df$p.value<0.001]<-'***'
df$Label[df$p.value<0.01 & is.na(df$Label)]<-'**'
df$Label[df$p.value<0.05 & is.na(df$Label)]<-'*'
ggplot(df, aes(x = conc, y = mean, color = Treatment)) +
geom_errorbar(aes(ymax = upper, ymin = lower, width = 0),position = position_dodge(width=0.5)) +
geom_point(aes(shape = Treatment, fill = Treatment), size = 4, position = position_dodge(width=0.5)) +
geom_text(aes(label = Label),size = 4, position = position_dodge(width =0.5), color = "black") +
scale_shape_manual(values = c(22, 21, 23)) +
scale_color_manual(values=c('blue','coral1', 'darkgreen' )) +
scale_fill_manual(values=c('blue','coral1', 'darkgreen')) +
labs(x = "Concentration (\u03BCM)", y = "Abs", title = "Viability", fill = "Treatment") +
scale_x_continuous(trans="log10", limits = c(0.5, 170), breaks = breaks) +
scale_y_continuous(limits = c(0, 1.5), breaks = breaks_y) +
theme_light() +
ggpubr::rotate_x_text(angle = 70) +
theme(axis.text = element_text(size = 12, face = "bold"),
axis.title.y = element_text(size = 12, face ="bold"),
axis.title.x = element_text(size = 12, face ="bold"))
How can I align the asterisk automatically to be directly above the correct dot with position_dodge?
Here is the data set:
d <- tribble(
~priceseg, ~price_n, ~zet_n, ~zet_n2,
"(0,1]", 16, 2, 24,
"(1,3]", 33, 3, 38,
"(3,5]", 33, 2, 25,
"(5,6]", 17, 1, 13,
)
And here is the visualisation thanks to #d.b
ggplot(d) +
geom_col(aes(x = priceseg, y = price_n), fill = ("#F1948A"), colour="black", size = 0.6) +
geom_line(data = d, mapping = aes(x = priceseg, y = zet_n2, group = 1), colour = "#154360", size = 1) +
geom_label(data = d, mapping = aes(x = priceseg, y = price_n, label = price_n), nudge_y = -0.6)
Now, I want to add the legend for bar plot and line in the visualisation something like this: Combined line & bar geoms: How to generate proper legend?
Also, I would like to add % in geom_label.
But somehow, I could not manage to implement it. Any help?
Here is an option
# Calculate percentage and add as column to `d`
d <- transform(d, perc = sprintf("%2.1f%%", price_n / sum(price_n) * 100))
# Plot
ggplot(d, aes(x = priceseg)) +
geom_col(aes(y = price_n, fill = "bar_data"), colour = "black", size = 0.6) +
geom_line(aes(y = zet_n2, group = 1, colour = "line_data"), size = 1) +
scale_fill_manual("", values = "#F1948A") +
scale_colour_manual("", values = "#154360") +
geom_label(aes(y = price_n, label = perc), nudge_y = -0.6) +
theme(
legend.key = element_blank(),
legend.title = element_blank(),
legend.box = "horizontal")
You can adjust the fill and colour "labels" by changing the strings "bar_data" and "line_data".
Reproducible data:
df <- data.frame(cbind("Thriving" = c(2, 2, NA, runif(9, 2.0, 5.0)), "Performance" = c(2, 3.5, 2.3, 4.2, NA, runif(7, 1.9, 6.9)), "Mastery_Climate" = c(runif(10, 2.2, 6.5), NA, 2.3), "Competitive_Climate" = c(NA, runif(4, 1.0, 3.6), NA, NA, runif(5, 1.5, 2.8)), "Collaboration" = c(runif(8, 2.2, 7.0), NA, NA, 5.5, 2.1)))
With this data I want to create bloxplots using the following command with the packages ggplot2 and tidyr:
df %>%
gather(key = "variable", value = "value") -> n
n$variable <- factor(n$variable, levels = c("Thriving", "Performance", "Mastery_Climate", "Competitive_Climate", "Collaboration"))
ggplot(data = n, aes(y = value, x = variable)) + stat_summary(fun.data = min.mean.sd.max, geom = "boxplot", col = "#323232", fill = "#EFC76C") +
coord_flip() + scale_y_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7)) +
expand_limits(y = c(1, 7)) +
labs(x = "", y = "") +
theme(text = element_text(size = 12), panel.background = element_rect(fill = "#EAEDED")) +
theme(plot.margin=unit(c(0, 2, 0, 1.8),"cm"))
The function used in stat_summary is as follows:
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
}
Now, HERE IT COMES: everything works beautifully, however, now I would like to colour the background in three different colours, green, yellow and red. I know that I have to use geom_rect for that. However, in order to have the boxplots in the foreground, I need to pass the geom_rect argument first - but this breaks my code:
df %>%
gather(key = "variable", value = "value") -> n
n$variable <- factor(n$variable, levels = c("Thriving", "Performance", "Mastery_Climate", "Competitive_Climate", "Collaboration"))
ggplot(data = n, aes(y = value, x = variable)) +
geom_rect(aes(xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = 3, fill = "green"), alpha = .01) +
geom_rect(aes(xmin = -Inf, xmax = Inf, ymin = 3, ymax = 5, fill = "yellow"), alpha = .01) +
geom_rect(aes(xmin = -Inf, xmax = Inf, ymin = 5, ymax = Inf, fill = "red"), alpha = .01) +
stat_summary(fun.data = min.mean.sd.max, geom = "boxplot", col = "#323232", fill = "#EFC76C") +
coord_flip() + scale_y_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7)) +
expand_limits(y = c(1, 7)) +
labs(x = "", y = "") +
theme(text = element_text(size = 12), panel.background = element_rect(fill = "#EAEDED")) +
theme(plot.margin=unit(c(0, 2, 0, 1.8),"cm"))
As you can see, I get the error "Error: Discrete value supplied to continuous scale". From research I understand that this is because I needed to change the sequence and it now is a problem that the x-variable is a factor. However, I have been unable to solve this.
It would be great if all the other code could stay the same, it took me ages to put it together. Also, once the boxplots are in the foreground, it would be great if the grid behind would still be visible. Furthermore, I was so confused by the fill in geom_rect, I put in "green" and I get pink, or I put "yellow" and get blue - no clue why.
In any case, any help is very much appreciated. Many greetings!
Edit: Updated answer with better shading control
I think this approach is more idiomatic to ggplot: this puts the shading into a separate table with numeric y values. In a modified ggplot call, all the y values are mapped as numeric values, but the labels for those values are swapped out in the scale_y_continuous line.
rects <- data.frame(xmin = -Inf,
xmax = Inf,
ymin = c(0,3,5),
ymax = c(3,5,Inf),
fill = c("green", "yellow", "red"))
ggplot(data = n, aes(y = value, x = as.numeric(variable))) +
geom_rect(data = rects, aes(xmin = xmin, xmax = xmax, ymin = ymin, ymax = ymax, fill = fill),
# Control the shading opacity here.
inherit.aes = FALSE, alpha = 0.15) +
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 = unique(n$variable)) +
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 = 12), panel.background = element_rect(fill = "#EAEDED")) +
theme(plot.margin=unit(c(0, 2, 0, 1.8),"cm"))
Original answer
geom_rect's coordinates should be pulled outside of the aes() call, and then I get a working solution. However, one problem with this approach is that the background rectangles are actually getting drawn once for each element in the source data, which is why the colors are so bright even with alpha = 0.01.
ggplot(data = n, aes(y = value, x = variable)) +
geom_rect(xmin = -Inf, xmax = Inf, ymin = 0, ymax = 3, fill = "green", alpha = .005) +
geom_rect(xmin = -Inf, xmax = Inf, ymin = 3, ymax = 5, fill = "yellow", alpha = .005) +
geom_rect(xmin = -Inf, xmax = Inf, ymin = 5, ymax = 7, fill = "red", alpha = .005) +
stat_summary(fun.data = min.mean.sd.max, geom = "boxplot", col = "#323232", fill = "#EFC76C") +
coord_flip() + scale_y_continuous(breaks = c(1, 2, 3, 4, 5, 6, 7)) +
expand_limits(y = c(1, 7)) +
labs(x = "", y = "") +
theme(text = element_text(size = 12), panel.background = element_rect(fill = "#EAEDED")) +
theme(plot.margin=unit(c(0, 2, 0, 1.8),"cm"))