I am using stat_ellipse in R to generate ellipse area polygons from the data. However, they overlap significantly and turning the alpha level to transparent "kind of" works. I wanted to see if there was a way to fill specific ellipses with a pattern that has a transparent background since they overlap so much. Maybe I could have some solid colors and others patterns?
This is my working plot code now:
ggplot(data = claw3,
aes(x = iso1,
y = iso2,
fill = group,
lty = community,
shape = community)) +
stat_ellipse(aes(group = interaction(group, community),
lty = community),
alpha = 0.85, #trasparent level trying to make 2012 West more visible
color = "black",
level = p.ell,
type = "norm",
geom = "polygon",
size = 1.1) +
geom_point(aes(fill = group), size = 2, alpha = 1, color = "black") +
scale_fill_manual(values = c("blue", "grey30","00FFFFFF"),labels = c("2012", "2014","2016"))+
scale_color_manual(values = c( "blue", "grey30","00FFFFFF"))+
scale_linetype_manual(values = c("dotted","solid"))+
scale_shape_manual(values = c(21, 24))+
guides(shape = guide_legend(override.aes = list(fill = "white")), #overrides legend for the community boxes filled white
fill = guide_legend(override.aes = list(shape = NA, size = 1))) + #overrides legend for group removes shapes in year
ylab(expression(paste(delta^{15}, "N (\u2030)"))) +
xlab(expression(paste(delta^{13}, "C (\u2030)"))) +
scale_x_continuous(breaks= seq(-26.5, -19.5, by = 1),
#labels = c( -24, rep("", 2), -23, rep("", 2), -21),
limits = c(-26.5, -19.5),
expand = c(0, 0)) +
scale_y_continuous(breaks= seq(4, 11),
labels = c(4, "",6, "",8, "", 10, ""),
limits = c(3.5, 11),
expand = c(0, 0)) +
theme(text = element_text(size=14)) +
theme_classic(base_size = 14) +
theme(legend.title = element_blank())
I have recently found ggpattern, but it does not look like its friendly with stat_ellipse or I really just don't understand where to put it. I believe Id have to remove the scale_fill_manual and scale_color_manual commands, but thats about it.
Related
I am trying to add labels to a ggplot object. The labels do not look neat and tidy due to their positioning. I have tried using various geom_label_repel and geom_text_repel options but am not having much luck.
I cannot share the data unfortunately, but I have inserted one of my codes below and a screenshot of one section of the redacted graph. The graph has multiple peaks that need labelling. Each label has 2 lines.
I would like the lines connecting the labels to be directly above each peak on the x axis, then turn at a right angle and the line continue horizontally slightly. I would then like the label to sit on top of this horizontal section of the line.
Some peaks are very close together, so the labels will end up being pushed up the y axis so they are able to stack up neatly.
I hope that description makes sense. I would appreciate it if anyone is able to help.
Thank you!
library(ggplot2)
library(ggrepel)
library(dplyr)
upper_plot <- ggplot() +
geom_point(data = plot_data[which(analysis == "Analysis1"),],
aes(x = rel_pos, y = logged_p, color = as.factor(chr)),
size = 0.25) +
scale_color_manual(values = rep(my_upper_colors, nrow(axis_df))) +
geom_point(data=upper_highlight_pos2_old,
aes(x = rel_pos, y = logged_p),
color= c('grey'),
size=0.75,
pch = 16) +
geom_point(data=upper_labels_old,
aes(x = rel_pos, y = logged_p),
color='dark grey',
size=2,
pch = 18) +
geom_point(data=upper_highlight_pos2_novel,
aes(x = rel_pos, y = logged_p),
color= c('black'),
size=0.75,
pch = 16) +
geom_point(data=upper_labels_novel,
aes(x = rel_pos, y = logged_p),
color='black',
size=2,
pch = 18) +
scale_x_continuous(labels = axis_df$chr,
breaks = axis_df$chr_center,
expand = expansion(mult = 0.01)) +
scale_y_continuous(limits = c(0, maxp),
expand = expansion(mult = c(0.02, 0.06))) +
# geom_hline(yintercept = -log10(1e-5), color = "red", linetype = "dashed",
# size = 0.3) +
geom_hline(yintercept = -log10(5e-8), color = "black", linetype = "dashed",
size = 0.3) +
labs(x = "", y = bquote(atop('GWAS', '-log'[10]*'(p)'))) +
theme_classic() +
theme(legend.position = "none",
axis.title.x = element_blank(),
plot.margin = margin(t=5, b = 5, r=5, l = 10)) +
geom_label_repel(data = upper_labels,
aes(x = rel_pos, y = logged_p, label = label),
ylim = c(maxp / 3, NA),
size = 2,
force_pull = 0,
nudge_x = 0.5,
box.padding = 0.5,
nudge_y = 0.5,
min.segment.length = 0, # draw all lines no matter how short
segment.size = 0.2,
segment.curvature = -0.1,
segment.ncp = 3,
segment.angle = 45,
label.size=NA, #no border/box
fill = NA, #no background
)
This is my current untidy layout...
EDIT:
This is the sort of layout I am after. The lines will need to be flexible and either be right-handed or left-handed depending on space (source: https://www.nature.com/articles/s41588-020-00725-7)
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?
My legend is not showing correctly when I am doing my graph in R using ggplot2. One column of my dataset is represented by a geom_bar and the two others are represented by geom_points (one shape each). The circle and the diamond shape are showing for both 2000 and 2008, the circle being in the diamong for both year. However, the graph works totally fine...
Here is a screenshot:
I have created a simplified version of my dataset:
order_var <- c(1, 4, 3, 5, 6, 2)
alt_name <- c('Agriculture', 'Mining', 'Food products',' Manufacture', 'Chemicals', 'Machinery')
y2000 <- c(20, 40, 50, 80, 30, 70)
y2008 <- c(40, 50, 80, 70, 30, 60)
y2018 <- c(10, 30, 80, 50, 40, 50)
datatest <- data.frame("order_var" = order_var, "alt_name" = alt_name, "y2000" = y2000, "y2008" = y2008, "y2018" = y2018)
And the code for my graph:
datatest %>% ggplot(aes(x = reorder(alt_name, order_var))) +
geom_bar(stat = "identity", aes(y = `y2018`, fill = "2018"), width = 0.7, col = "black") +
geom_point(aes(y = `y2008`, col = "2008"), shape = 23, fill = "white", size = 5) +
geom_point(aes(y = `y2000`, col = "2000"), shape = 19, fill = "black", size = 3) +
xlab("Industry") +
ylab("Percentage") +
theme(legend.position = "top") +
scale_fill_manual(name = '', values = c("2018" = "#4F81BD"), breaks = c("2018")) +
scale_colour_manual(name = '', values = c("2008" = "black", "2000" = "orange"))
If you know how to correct this problem, I would be very grateful!!
Thank you :)
That's a very tricky plot you are trying to make because you are in essence mapping the same aesthetics to different geoms.
The first thing you should do is to reshape your data to the long format. I also divided your dataset between 2018 (the bar), and 2000, 2008 (the points).
df2 <- datatest %>%
pivot_longer(cols = -c(order_var, alt_name)) %>%
mutate(bar = if_else(name == "y2018", 1, 0))
data_bar <- df2 %>% filter(bar == 1)
data_point <- df2 %>% filter(bar != 1)
I also find it useful to add a dodge to your points to avoid overlapping one inside the other as in the case of chemicals with position = position_dodge(width = 0.6).
The first solution gives what you want, but it is a bit of a hack, and I wouldn't recommend doing it as a general strategy. You basically add an aesthetics that you are not going to use to the bars (in this case, linetype), and then override it, as suggested in this answer.
ggplot(data_bar, aes(x = reorder(alt_name, order_var))) +
geom_bar(aes(y = value, linetype = name), fill = "#4F81BD", stat = 'identity', color = 'black') +
geom_point(data = data_point, position=position_dodge(width=0.6), aes(y = value, color = name, shape = name, size = name, fill = name)) +
scale_colour_manual(values = c("orange", "black"), labels = c("2000", "2008")) +
scale_fill_manual(values = c("orange", "white"), labels = c("2000", "2008")) +
scale_shape_manual(values = c(19, 23), labels = c("2000", "2008")) +
scale_size_manual(values = c(3, 5), labels = c("2000", "2008")) +
scale_linetype_manual(values = 1, guide = guide_legend(override.aes = list(fill = c("#4F81BD"))), labels = c("2018")) +
theme(legend.position = "top", legend.title = element_blank()) +
labs(x = "Industry", y = "Percentage")
Another solution, more general, is to avoid using the fill aesthetics for the geom_point and changing the shape to a solid one instead:
ggplot(data_bar, aes(x = reorder(alt_name, order_var))) +
geom_bar(aes(y = value, fill = name), stat = 'identity', color = "black") +
geom_point(data = data_point, position=position_dodge(width=0.6), aes(y = value, color = name, shape = name, size = name)) +
scale_fill_manual(values = c("#4F81BD"), labels = c("2018")) +
scale_colour_manual(values = c("orange", "white"), labels = c("2000", "2008")) +
scale_shape_manual(values = c(19, 18), labels = c("2000", "2008")) +
scale_size_manual(values = c(4, 6), labels = c("2000", "2008")) +
theme(legend.position = "top", legend.title = element_blank()) +
labs(x = "Industry", y = "Percentage")
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"))
I was trying to plot some predicted vs. actual data, something that resembles the following:
# Some random data
x <- seq(1: 10)
y_pred <- runif(10, min = -10, max = 10)
y_obs <- y_pred + rnorm(10)
# Faking a CI
Lo.95 <- y_pred - 1.96
Hi.95 <- y_pred + 1.96
my_df <- data.frame(x, y_pred, y_obs, Lo.95, Hi.95)
ggplot(my_df, aes(x = x, y = y_pred)) +
geom_line(aes(colour = "Forecasted Data"), size = 1.2) +
geom_point(aes(x = x, y = y_obs, colour = "Actual Data"), size = 3) +
geom_ribbon(aes(ymin=Lo.95, ymax=Hi.95, x=x, linetype = NA, colour = "Confidence Interval"), alpha=0.2) +
theme_grey() +
scale_colour_manual(
values = c("gray30", "blue", "red"),
guide = guide_legend(override.aes = list(
border=c(NA, NA, NA),
fill=c("gray30", "white", "white"),
linetype = c("blank", "blank", "solid"),
shape = c(NA, 19, NA))))
The plot looks like this:
The only issue I have with this plot is the red border surrounding the legend item symbol for the line (i.e. the forecasted data). Is there any way I can remove it without breaking the rest of my plot?
I think geom_ribbon was the problem. If we take its color & fill out of aes, everything looks fine
library(ggplot2)
# Some random data
x <- seq(1: 10)
y_pred <- runif(10, min = -10, max = 10)
y_obs <- y_pred + rnorm(10)
# Faking a CI
Lo.95 <- y_pred - 1.96
Hi.95 <- y_pred + 1.96
my_df <- data.frame(x, y_pred, y_obs, Lo.95, Hi.95)
m1 <- ggplot(my_df, aes(x = x, y = y_pred)) +
geom_point(aes(x = x, y = y_obs, colour = "Actual"), size = 3) +
geom_line(aes(colour = "Forecasted"), size = 1.2) +
geom_ribbon(aes(x = x, ymin = Lo.95, ymax = Hi.95),
fill = "grey30", alpha = 0.2) +
scale_color_manual("Legend",
values = c("blue", "red"),
labels = c("Actual", "Forecasted")) +
guides( color = guide_legend(
order = 1,
override.aes = list(
color = c("blue", "red"),
fill = c("white", "white"),
linetype = c("blank", "solid"),
shape = c(19, NA)))) +
theme_bw() +
# remove legend key border color & background
theme(legend.key = element_rect(colour = NA, fill = NA),
legend.box.background = element_blank())
m1
As we leave Confidence Interval out of aes, we no longer have its legend. One workaround is to create an invisible point and take one unused geom to manually create a legend key. Here we can use size/shape (credit to this answer)
m2 <- m1 +
geom_point(aes(x = x, y = y_obs, size = "Confidence Interval", shape = NA)) +
guides(size = guide_legend(NULL,
order = 2,
override.aes = list(shape = 15,
color = "lightgrey",
size = 6))) +
# Move legends closer to each other
theme(legend.title = element_blank(),
legend.justification = "center",
legend.spacing.y = unit(0.05, "cm"),
legend.margin = margin(0, 0, 0, 0),
legend.box.margin = margin(0, 0, 0, 0))
m2
Created on 2018-03-19 by the reprex package (v0.2.0).
A better way to address this question would be to specify show.legend = F option in the geom_ribbon(). This will eliminate the need for the second step for adding and merging the legend key for the confidence interval. Here is the code with slight modifications.
ggplot(my_dff, aes(x = x, y = y_pred)) +
geom_line(aes(colour = "Forecasted Data"), size = 1) +
geom_point(aes(x = x, y = y_obs, colour = "Actual Data"), size = 1) +
geom_ribbon(aes(ymin=Lo.95, ymax=Hi.95, x=x, linetype = NA, colour = "Confidence Interval"), alpha=0.2, show.legend = F) +
theme_grey() +
scale_colour_manual(
values = c("blue", "gray30", "red"))+
guides(color = guide_legend(
override.aes = list(linetype = c(1, 1, 0)),
shape = c(1, NA, NA),
reverse = T))
My plot
Credit to https://stackoverflow.com/users/4282026/marblo
for their answer to similar question.