overlay geom_point with position=dodge and facet grid in ggplot2 - r

Considering the following data, I am able to generate a plot which describes how the risk of a react over a time interval changes.
risk_1 <- c(0.121,0.226,0.333,0.167,0.200,0.273,0.138,0.323,0.394,0.250,0.200,0.545,0.190,0.355,0.515,0.333,0.300,0.818)
risk_minus_SE <- c(0.060,0.114,0.198,0.047,0.057,0.097,0.072,0.186,0.247,0.089,0.057,0.280,0.109,0.211,0.352,0.138,0.108,0.523)
risk_plus_SE <- c(0.229,0.398,0.504,0.448,0.510,0.566,0.249,0.499,0.563,0.532,0.510,0.787,0.309,0.531,0.675,0.609,0.603,0.949)
Status <- rep(c(rep('With placebo',3),rep('With drug',3)),3)
durtn <- rep(c('(3-15]','(15-30]','(30-46]'),6)
react <- c(rep("x\u226516",6),rep("x\u226509",6),rep("x\u226504",6))
df1 <- data.frame(risk_1, risk_minus_SE, risk_plus_SE, Status, durtn, react)
dodge <- position_dodge(width=0.45)
ggplot(df1,aes(colour=react, y=risk_1, x=durtn)) +
geom_point(aes(shape=durtn), shape=16, size = 5, position=dodge) +
geom_errorbar(aes(ymin=risk_minus_SE, ymax=risk_plus_SE), position = dodge, width=0.5, size=1, lty=1) +
scale_colour_manual(values = c('black','red','blue')) +
facet_grid(~Status) +
scale_shape_manual(values = c(8,19))+
theme_bw() +
scale_x_discrete(limits=c('(3-15]','(15-30]','(30-46]')) +
coord_cartesian(ylim = c(0, 0.8)) +
theme(legend.position = c(.1, .85), legend.background = element_rect(colour = "black"),
plot.title = element_text(lineheight=1.5, face="bold", size=rel(1.5), hjust = 0.5),
panel.grid.major.x = element_blank(),
axis.text.x = element_text(vjust=0.5, size=16),
axis.text.y = element_text(vjust=0.5, size=16),
axis.title.y = element_text(size=20),
axis.title.x = element_text(size=20),
legend.text = element_text(size = 16, face = "bold"),
strip.text = element_text(size=25)) +
xlab("\ntime (min)") + ylab("Risk")
What I want to do is overlay a series of points at given x and y coordinates.
That being at With drug & durtn==(3,15], manually insert points at.....
Risk==0.5 for react=x≥04 in black
Risk==0.2 for react=x≥09 in red
Risk==0.0 for react=x≥16 in blue
Such that the desired output should look like
How does one use the geom_point() in combination with a facet_grid and dodge

First, you have to create a separate data frame that contains the data for the additional points.
dat <- data.frame(risk_1 = c(0.5, 0.2, 0),
react = levels(df1$react),
durtn = '(3-15]',
Status = 'With drug')
This new data frame dat can be used with geom_point to add an additional layer to the existing plot.
+ geom_point(data = dat, position = dodge, shape = 4, size = 5, show.legend = FALSE)

Related

Creating Dual Axis plot (bar and line)

I want to create a dual axis plot in ggplot R with a dual bar and line plot, like this one created in excel.
The y axis scales are different.
my data is as follows;
I've created a bar plot and line plot. But unsure on how to put them together (I've tried man various ways and they don't seem to work).
Here is my code for the bar plot.
inf_conc <- ggplot(data=data, aes(x=Day, y=inf)) +
geom_bar(stat="identity", width=0.4, color="red3", fill="red3") +
ggtitle("Influent Microplastic Concentration \n and Flow Rate") +
# \n splits long titles into multiple lines
xlab("Day") +
ylab("Microplastic Concentration (MPs/L)") +
scale_y_continuous(limits =c(0, 50), breaks = seq(0, 50, 5))
inf_conc + theme(axis.text = element_text(size = 20, colour = "black"),
plot.title = element_text(size =25, hjust = 0.5,
face = "bold"), axis.title = element_text(size = 20,
face = "bold", margin = 5))
inf_conc + theme(axis.text = element_text(size = 20, colour = "black"),
plot.title = element_text (size =25, hjust = 0.5, face = "bold"),
axis.title = element_text(size = 20, face = "bold", margin = 20))
and here is the code for the line plot:
inf_flow <- ggplot(data=data, aes(x=Day, y=flow, group = 1)) +
geom_line(stat = "identity", colour ="blue4") +
geom_point(colour ="blue4") +
ylab("Inlet flow L/s")+
xlab("Day")+
scale_y_continuous(limits=c(0,800), breaks = seq(0, 800, 100))
inf_flow + theme(axis.text = element_text(size = 20, colour = "black"),
plot.title = element_text (size =25, hjust = 0.5, face = "bold"),
axis.title = element_text(size = 20, face = "bold", margin = 5))
inf_flow + theme(axis.text = element_text(size = 20,
colour = "black"), plot.title = element_text (size =25, hjust = 0.5,
face = "bold"), axis.title = element_text(size = 20, face = "bold",
margin = 20))
Can anyone help with how I can get these onto one dual axis graph please.
GGplot doesn't make it especially easy, but you can do it:
library(ggplot2)
my_dat <- data.frame(
Day = paste("Day",rep(1:3, each=3), rep(c("(AM)", "(Midday)", "(PM)"), 3), sep= " "),
day_num = 1:9,
inf = seq(from = 13,to = 45, length=9),
flow = runif(9, 580, 740)
)
ggplot() +
geom_bar(data=my_dat, aes(x=day_num, y=inf, fill = "Influent Concentration"), stat="identity", width=.6) +
geom_line(data=my_dat, aes(x=day_num, y=flow*(50/800), colour="FLow Rate. L/s")) +
scale_fill_manual(values="red") +
scale_colour_manual(values="blue") +
scale_x_continuous(breaks=1:9, labels=my_dat$Day) +
scale_y_continuous(sec.axis = sec_axis(trans = ~.x*800/50, name = "Flow Rate L/S"), limits = c(0,50), name = "Influent. MPs/L") +
labs(fill="", colour="", x="") +
theme(legend.position="bottom",
axis.text.x = element_text(angle=45, hjust=1))
Created on 2023-01-17 by the reprex package (v2.0.1)
The main things you have to do are to
Transform the second-axis series to have the same range(ish) as the first-series axis. In your case, the excel graph had the second y-axis going from 0-800 and the first y-axis going from 0-50, so the transformation is simple, you multiply the second series values by 50/800.
In the scale_y_continuou() function there is an argument sec.axis which allows you to plot a second axis on the right-hand side of the plot. Here, you need to specify the trans argument to transform the values you're plotting back into the original values. That's what trans = ~.x*800/50 does.
EDIT: Modifying OP's code
I modified your code as much as I can without actually having the data. The picture of the data that you provided does not give enough information about the data, if you use dput(data) and post the results, I could likely help more. For now, try this:
inf_plot <- ggplot(data=data, aes(x=Day))+
geom_bar(aes(y=inf, fill="Influent conc"), stat = "identity", width=0.4)+
geom_line(aes(y=flow*(50/800), colour="flow rate"), size = 1.4, group=1)+
ggtitle("Influent Microplastic Concentration \n and Influent Flow Rate")+
xlab("\n\nDay") +
ylab("Microplastic Concentration (MPs/L)\n\n")+
scale_fill_manual(values="red4") +
scale_colour_manual(values="blue4") +
scale_y_continuous(sec.axis = sec_axis(~.*800/50, name = "Inlet flow rate (L/s)\n\n"), limits = c(0,50))
inf_plot + theme(axis.text = element_text( size = 20, colour = "black"),
plot.title = element_text (size =25, hjust = 0.5, vjust = 5, face = "bold"),
axis.title = element_text (size = 20, face = "bold"),
plot.margin =unit(c(1.5, 1.5, 1.5, 1.5), "cm"),
legend.position = "bottom")
The answer was a great help in how to transform my axis.
Initially produced the graph a slightly different way, but incorporated the same transformation of axis.
However, I can't seem to get the legend to appear at the bottom of the graph with the following code.
inf_plot <- ggplot(data=data, aes(x=Day))+
geom_bar(aes(y=inf, fill="Influent conc"), stat = "identity", width=0.4,
colour="red4", fill = "red4")+
ggtitle("Influent Microplastic Concentration \n and Influent Flow Rate")+
xlab("\n\nDay") +
ylab("Microplastic Concentration (MPs/L)\n\n")+
geom_line(aes(y=flow*(50/800), colour="flow rate"), size = 1.4, colour ="blue4", group = 1)+
scale_fill_manual(values="red4") +
scale_colour_manual(values="blue4") +
scale_y_continuous(sec.axis = sec_axis(~.*800/50, name = "Inlet flow rate (L/s)\n\n"), limits = c(0,50))
inf_plot + theme(axis.text = element_text( size = 20, colour = "black"),
plot.title = element_text (size =25, hjust = 0.5, vjust = 5, face = "bold"),
axis.title = element_text (size = 20, face = "bold"),
plot.margin =unit(c(1.5, 1.5, 1.5, 1.5), "cm"),
legend.position = "bottom")
enter image description here

Dodge failing in violin plot

I would like to plot the congruence effects (incongruent minus congruent) as a violin plot per combination of stimulus age and response type. This is what my code looks like so far. I am not yet satisfied with the representation. How can I change it so that for each of the four conditions (adult frown, adult smile, child frown, child smile) I get the corresponding violin plot horizontally next to each other? Thanks in advance for the help. Attached is the code and an excerpt from the data frame.
violin plot
dataset$congruency_effect <- ifelse(dataset$congruency == "congruent", dataset$avgAmplitude, -dataset$avgAmplitude)
p <- ggplot(dataset, aes(x = stimulusResponse, y = congruency_effect, fill = congruency_effect, group = stimulusAge)) +
geom_violin() +
geom_point(position = position_dodge(width = 0.75), size = 3, stat = "summary", fun.y = "mean") +
scale_fill_manual(values = c("#F8766D", "#00BFC4")) +
ggtitle("Conventional EEG 350-450 ms") +
scale_y_continuous(limits = c(-5, 5)) +
facet_wrap(~stimulusAge, scales = "free_x")
EEG_Conventional450_age_response <- p + theme(
# Set the plot title and axis labels to APA style
plot.title = element_text(face = "bold", size = 16),
axis.title = element_text(face = "bold", size = 14),
# Set the axis tick labels to APA style
axis.text = element_text(size = 12),
# Set the legend title and labels to APA style
legend.title = element_text(face = "bold", size = 14),
legend.text = element_text(size = 12),
# Set the plot and panel backgrounds to white
panel.background = element_rect(fill = "white"),
plot.background = element_rect(fill = "white")
)
EEG_Conventional450_age_response
excerpt data frame
several permutations of arguments in ggplot
This has to do with the grouping aesthetic. Remove it, and your plot works.
library(ggplot2)
set.seed(42)
dataset <- data.frame(stimulusResponse = rep(c("frown", "smile"), each = 20),
congruency_effect = rnorm(40),
stimulusAge = rep(c("baby", "adult"), 20))
## removed group = stimulusAge
ggplot(dataset, aes(x = stimulusResponse, y = congruency_effect)) +
geom_violin() +
geom_point(position = position_dodge(width = 0.75), size = 3, stat = "summary") +
facet_wrap(~stimulusAge, scales = "free_x")

Why a second legend is not being included in my ggplot?

The plot below is to create a ggplot in which I show the relationship between two variables according to the raw data (points) and according to two different models (m1 and m3), from which I extract the coefficients and I drow two continuous lines. The grey line is just to show a relationship of 1:1.
line_colors <- RColorBrewer::brewer.pal(7, "Reds")[c(2,4,6)]
line_colors
Plot_a <- ggplot(Todo.6min, aes(x=VeDBA.V13AP, y=VeDBA.X16, colour=ID)) +
geom_point(size=1.5,alpha=0.2) +
geom_abline(aes(slope=1,intercept=0),linetype="dashed",color="grey52",size=1.5) +
theme_bw() +
theme(strip.background=element_blank(),
axis.title.x =element_blank(),
axis.title.y =element_blank(),
axis.text.x = element_text(angle = 0, hjust = 0.5,size = 15),
axis.text.y = element_text(angle = 0, hjust = 0.5,size = 15),
axis.line = element_line(),
panel.grid.major= element_blank(),
panel.grid.minor = element_blank(),
legend.position = "right",
legend.text=element_text(size=18),
legend.title = element_text(size=19, face = "bold"),
legend.key=element_blank(),
panel.border = element_blank(),
strip.placement = "outside") +
guides(color=guide_legend(override.aes=list(fill=NA)))
Plot_a
Plot_b <- Plot_a +
geom_abline(aes(linetype = "m1"),slope = fixef(mod2b)[2] , intercept = fixef(mod2b)[1], color = line_colors[1], size=1.5) +
geom_abline(aes(linetype = "m3"),slope = fixef(mod2d)[2] + fixef(mod2d)[3], intercept = fixef(mod2d)[1], color = line_colors[2], size=1.5) +
scale_linetype_manual(values = c(m1 = "solid", m3 = "solid"),labels = c(m1 = "m1", m3 = "m3")) +
labs(color = "ID", linetype = expression(Model)) +
guides(linetype = guide_legend(override.aes = list(color = line_colors)))
Plot_b
My doubt is why I do not get a legend for the continuous lines although I used scale_linetype_manual for indicating that I wanted a legend in which appears "m1" and "m3" as legend.text.
Does anyone know where is the mistake?
My suggestion would be to manually populate the mapping of geom_abline(), and then cut the data so that it matches the number of lines you're drawing. Illustrated below with an inbuilt dataset.
library(ggplot2)
ggplot(iris, aes(Sepal.Width, Sepal.Length)) +
geom_abline(aes(linetype = c("m1", "m3"),
slope = c(0.5, 0.75),
intercept = c(0, 0.5)),
data = iris[1:2,])
Created on 2020-11-06 by the reprex package (v0.3.0)
For your use case you'd have to substute slope = c(0.5, 0.75) by slope = c(fixef(mod2b)[2], fixef(mod2d)[2]), etc.

How to change size of points of legend when 2 legends are present

I have a graph where two legends are present. I need to change the size of the points of one of the legends.
I need to change the bullet size of "market type" in the legend. I use the example here but does not work for my graph.
My code is below:
k <- ggplot(subsetdf) + theme_bw() +
geom_point( aes(y=y, x=x, size =Total.Unit.Count, fill = region), shape=21)+
scale_colour_hue(aes(y=y, x=x),l=50) + # Use a slightly darker palette than normal
geom_text_repel (aes(y=y, x=x, label = rownames(subsetdf))) +
geom_smooth(aes(x=x, y=y),method=lm, # Add linear regression lines
se=FALSE) +
labs(y = "title", x = "title",
title = "title",
size = "size", fill = "fill")+
theme(plot.title = element_text (face = 'bold',size = 21,hjust = 0.5),
legend.text = element_text(size = 16),
legend.title = element_text(size = 18),
axis.title.x = element_text(size=20),
axis.title.y = element_text(size=20),
axis.text.x = element_text(size = 18,angle=45, hjust=1),
axis.text.y = element_text(size = 18,hjust = 1),
panel.grid.major = element_blank(),
panel.grid.minor = element_blank())+
scale_size_continuous(range = c(3,8))+
guides(colour = guide_legend(override.aes = list(size=10)))
You used the fill aesthetic guide, not color. So that is the guide to override.
Below is an example with iris dataset, as you code is not reproducible.
library(ggplot2)
ggplot(iris) +
geom_point(aes(Sepal.Length, Petal.Length, size = Sepal.Width, fill = Species), shape = 21) +
guides(fill = guide_legend(override.aes = list(size=8)))

How to add extra legend to a map plot in ggplot2 based on column entries?

Data: Data
Code:
palette = brewer.pal(11,"RdYlGn") # ColorBrewewr.org spectral palette, 11 colors
ggmap_byscen = ggplot(wmap_byscen.df[wmap_byscen.df$variable !=c("AVG") &
wmap_byscen.df$ID_1 !=c("0"),], aes(x=long, y=lat, group=group))
ggmap_byscen = ggmap_byscen + geom_polygon(aes(fill=value)) + facet_wrap(~ variable)
ggmap_byscen = ggmap_byscen + geom_path(colour="grey50", size=.1)
ggmap_byscen = ggmap_byscen + geom_text(aes(x=c.long, y=c.lat, label=ID_1),size=5)
ggmap_byscen = ggmap_byscen + scale_fill_gradientn(name="% Change",colours=palette)
ggmap_byscen = ggmap_byscen + coord_fixed(xlim = longlimits, ylim = latlimits)
ggmap_byscen = ggmap_byscen + scale_y_continuous(breaks=seq(-60,90,30), labels=c("60ºS","30ºS","0º","30ºN","60ºN","90ºN"))
ggmap_byscen = ggmap_byscen + scale_x_continuous(breaks=seq(-180,180,45), labels=c("180ºW","135ºW","90ºW","45ºW","0º","45ºE","90ºE","135ºE","180ºE"))
ggmap_byscen = ggmap_byscen + labs(x="",y="",title="Average yield impacts across all crops across\nby climate scenarios (% change)")
ggmap_byscen = ggmap_byscen + theme(plot.title=element_text(size=rel(2), hjust=0.5, vjust=1.5, face="bold"),
legend.text=element_text(size=17),
legend.position="left",legend.text=element_text(size=rel(1.3)),
legend.title=element_text(size=rel(1.4), hjust=0.5, vjust=1),
panel.background = element_rect(fill = "white", colour = "gray95"),
strip.text = element_text(size=18),
axis.text.x = element_text(size=16),
axis.text.y = element_text(size=16))
ggmap_byscen
Result:
Question: I am looking to add an additional legend defined by the column "label" in the dataframe to identify the region on the map. Preferably, I'd like the legend to be below the faceted map. I have seen examples where one can add a table entry as a separate plot and then merge the two. I could not figure out how to make it for my case.
Any help would be great, thanks.
As #jlhoward mentioned, longlimits and latlimits are not defined. I, therefore, decided to leave coord_fixed(xlim = longlimits, ylim = latlimits) part from this answer. My workaround works, but I am sure there are better ways to work on this. The challenge was to create another legend in a way it can present the data well. If you use colour in geom_text, you can create another legend, but you end up seeing the alphabet, a in the grey boxes in the legend. So, I decided to use geom_point with alpha = 0 as well as colour in aes. In this way, you have a new legend with ID names, but you do not see any points on the maps. Then, I used annotate to assign the numbers on the maps. Thanks to #jlhoward, I created a small data frame which is necessary for annotate(). If you use the original data frame, R tries to write the texts 4000 times or so. In the theme part, I added legend.key = element_rect(fill = NA) in order to remove grey squares in the legend. I made the height and width of the figure pretty small so that I could post it here. So it does not look that great. But if you specify large numbers, the figure will look better.
library(dplyr)
library(ggplot2)
wmap_byscen.df <- read.csv("mydata.csv", header = T)
mydf <- wmap_byscen.df[wmap_byscen.df$variable != c("AVG") &
wmap_byscen.df$ID_1 != c("0"),]
### This is for annotate()
mydf2 <- select(mydf, c.long, c.lat, ID_1, ID_name) %>%
distinct()
### Color setting
palette = brewer.pal(11,"RdYlGn")
ggplot(mydf, aes(x = long, y = lat, group = group)) +
geom_polygon(aes(fill = value)) +
facet_wrap(~ variable) +
geom_path(colour = "grey50", size = .1) +
geom_point(aes(x = c.long, y = c.lat, color=factor(ID_name, levels=unique(ID_name)), label = ID_1), size = 1, alpha = 0) +
annotate("text", x = mydf2$c.long, y = mydf2$c.lat, label = mydf2$ID_1) +
scale_fill_gradientn(name = "% Change",colours = palette) +
scale_color_discrete(name = "Regions") +
#coord_fixed(xlim = longlimits, ylim = latlimits) +
scale_y_continuous(breaks = seq(-60,90,30), labels = c("60ºS","30ºS","0º","30ºN","60ºN","90ºN")) +
scale_x_continuous(breaks = seq(-180,180,45), labels = c("180ºW","135ºW","90ºW","45ºW","0º","45ºE","90ºE","135ºE","180ºE")) +
labs(x = "",y = "",title = "Average yield impacts across all crops across\nby climate scenarios (% change)") +
theme(plot.title = element_text(size = rel(2), hjust = 0.5, vjust = 1.5, face = "bold"),
legend.text = element_text(size = 8),
legend.position = "bottom",
legend.text = element_text(size = rel(1.3)),
legend.title = element_text(size = rel(1.4), hjust = 0.5, vjust = 1),
panel.background = element_rect(fill = "white", colour = "gray95"),
strip.text = element_text(size = 18),
axis.text.x = element_text(size = 16),
axis.text.y = element_text(size = 16),
legend.key = element_rect(fill = NA)) +
guides(col = guide_legend(nrow = 3, byrow = TRUE))

Resources