Creating a simple Graph in R - r

how can I create this in R?:
I can't seem to get the data.frame right in order to display the variables correctly.

It can be created step by step with "base R" functions. It can be done with data frames, but simple vectors will also do here.
create data sets for A and B
plot both with steps type="s"
optionally: suppress default axes and make your own, with labels from 0.95 to 1.00 only
add a legend
optionally: add the two hand-drawn red points
x <- seq(0.94, 1.0, 0.01)
A <- seq(0, 1, length.out = length(x))
x2 <- c(0.94, 1, 1.01)
B <- c(0, 1, 1)
plot(x, A, type = "s", xlim = c(0.94, 1.01), ylab = "F(x)", axes = FALSE)
lines(x2, B, type = "s", col = "blue")
axis(1, at=pretty(c(0.95, 1)))
axis(2)
box()
legend("topleft", lty=1,
legend = c("Lotterie A", "Lotterie B"),
col = c("black", "blue"))
points(c(1, 1), c(0, 1), col = "red")

Something like this?
df1 <- data.frame(x = rep(seq(0.95:1, by = 0.01), 2), cat = "A")
df1 <- df1[order(df1$x), ]
y <- c(rep(seq(0, 1, by = 1/6), 2))
df1$y <- sort(y)[2:13]
df2 <- data.frame(x = c(0, 1, 1, 1.5), y = c(0, 0, 1, 1), cat = "B")
df <- rbind(df1, df2)
library(ggplot2)
ggplot(df, aes(x, y, colour = cat)) +
geom_path() +
coord_cartesian(xlim = c(0.95, 1)) +
scale_y_continuous(breaks = seq(0, 1, by = 0.2))

Related

ggplot2 plot two columns with same x axis

I have a data frame with 3 columns:
A date time column
water level of a pond over 2 years (hourly)
daily precipitation over 2 years (daily)
I want to plot the date time on the x axis and the other two as two separate y axis.
I've tried with ggplot2, but this seems like quite a tricky thing to do. Does anyone know of any solutions or of any other methods.
Thankyou.
This is my current code. I don't know how to add in the data for a second axis however. (It is in a for loop as I have multiple locations within the pond. They all have the same data layout.)
scaleFUN <- function(x) sprintf("%.2f", x)
plotlist_mAODdate <- list()
j = 1 # counter for plot title and index
for (datTime in mAODdata){
plotName <- names(mAODdata)[j]
j = j+1
plot <-
datTime %>%
ggplot() +
geom_point(aes_string(x='DateTime', y='Rel_mAOD'), col='grey') +
geom_smooth(aes_string(x='DateTime', y='Rel_mAOD')) +
theme_classic() +
labs(y='Water Depth (mAOD)', x=NULL) +
ggtitle(plotTitles[[plotName]][1]) +
scale_x_datetime(
breaks=seq(min(datTime$DateTime), max(datTime$DateTime),
by= "6 months"), date_labels="%b-%y") +
scale_y_continuous(labels=scaleFUN) +
geom_vline(xintercept=as.POSIXct('2020-11-03 01:00:00'), col='red') +
geom_vline(xintercept=as.POSIXct('2021-11-01 01:00:00'), col='red', linetype='dashed') +
theme(text=element_text(size=20, family='Calibri Light')) +
theme(plot.margin = unit(c(1, 1, 1, 1), 'cm')) +
theme(axis.title.y=element_text(margin=margin(t=0, r=20, b=0, l=0))) +
theme(axis.title.x=element_text(margin=margin(t=20, r=0, b=0, l=0)))
plotlist_mAODdate[[plotName]] <- plot
}
Since you mentioned other methods, you can do this in base R by:
Data
df <- data.frame(date = seq(as.Date('2021-01-01'),as.Date('2022-12-31'), by = 1),
water = 250 + 1:730*2,
precipitation = 0 + (1:730)^2)
Code
par(mar = c(5.1, 4.1, 4.1, 4.1))
plot(x = df$date, y = df$water, type = "l", col = "red", bty = "n", ylab = "", xlab = "")
par(new = TRUE)
plot(x = df$date, y = df$precipitation, type = "l", col = "blue", axes = FALSE, xlab = "", ylab = "")
axis(side = 4)
mtext("Year", side = 1, padj = 4)
mtext("Water", side = 2, padj = -4)
mtext("Precipitation", side = 4,, padj = 4, srt = -90)
legend("topleft", c("Water","Precipitation"), lty = 1, col = c("red","blue"), bty = "n")
Output
Multiple locations
If you have multiple locations, you can do:
Data
set.seed(123)
df2 <- data.frame(date = seq(as.Date('2021-01-01'),as.Date('2022-12-31'), by = 1),
water = 250 + 1:730*2,
precipitation = 0 + (1:730)^2,
location = sample(LETTERS[1:4], 730, replace = TRUE))
Code
par(mfrow = c(floor(length(unique(df2$location))/2), 2), mar = c(5.1, 4.1, 4.1, 4.1))
for(i in sort(unique(df2$location))){
plot(x = df2[df2$location == i, "date"], y = df2[df2$location == i, "water"], type = "l", col = "red", bty = "n", ylab = "", xlab = "")
par(new = TRUE)
plot(x = df2[df2$location == i, "date"], y = df2[df2$location == i, "precipitation"], type = "l", col = "blue", axes = FALSE, xlab = "", ylab = "")
axis(side = 4)
mtext(paste0("Location: ", i), side = 3, adj = 0)
mtext("Year", side = 1, padj = 4)
mtext("Water", side = 2, padj = -4)
mtext("Precipitation", side = 4,, padj = 4, srt = -90)
legend("topleft", c("Water","Precipitation"), lty = 1, col = c("red","blue"), bty = "n")
}
Output
I used the sec.axis method with
geom_point(aes(y=(prcp_amt/150)+72), col='blue')
and
scale_y_continuous(sec.axis = sec_axis(~(.-72)*150, name='Precipitation (mm)')
and rescaling the data, so they both fit on the same scale. I know this isn't the best method, but I needed the rest of the ggplot2 to make the appearance of the graphs. This is how it's incorporated into the full code.
scaleFUN <- function(x) sprintf("%.2f", x)
plotlist_mAODdate <- list()
j = 1 # counter for plot title and index
for (datTime in mAODdata){
plotName <- names(mAODdata)[j]
j = j+1
plot <-
datTime %>%
ggplot(aes(x=DateTime)) +
geom_point(aes(y=Rel_mAOD), col='grey') +
geom_smooth(aes(y=Rel_mAOD), col='black') +
geom_point(aes(y=(prcp_amt/150)+72), col='blue') +
theme_classic() +
labs(y='Water Depth (mAOD)', x=NULL) +
ggtitle(plotTitles[[plotName]][1]) +
scale_x_datetime(
breaks=seq(min(datTime$DateTime), max(datTime$DateTime),
by= "6 months"), date_labels="%b-%y") +
scale_y_continuous(labels=scaleFUN, sec.axis = sec_axis(~(.-72)*150, name='Precipitation (mm)')) +
geom_vline(xintercept=as.POSIXct('2020-11-03 01:00:00'), col='red') +
geom_vline(xintercept=as.POSIXct('2021-11-01 01:00:00'), col='red', linetype='dashed') +
theme(text=element_text(size=20, family='Calibri Light')) +
theme(plot.margin = unit(c(1, 1, 1, 1), 'cm')) +
theme(axis.title.y=element_text(margin=margin(t=0, r=20, b=0, l=0))) +
theme(axis.title.x=element_text(margin=margin(t=20, r=0, b=0, l=0)))
plotlist_mAODdate[[plotName]] <- plot
}

Merge separate divergent size and fill (or color) legends in ggplot showing absolute magnitude with the size scale

I am plotting some multivariate data where I have 3 discrete variables and one continuous.
I want the size of each point to represent the magnitude of change rather than the actual numeric value. I figured that I can achieve that by using absolute values. With that in mind I would like to have negative values colored blue, positive red and zero with white. Than to make a plot where the legend would look like this:
I came up with dummy dataset which has the same structure as my dataset, to get a reproducible example:
a1 <- c(-2, 2, 1, 0, 0.5, -0.5)
a2 <- c(-2, -2, -1.5, 2, 1, 0)
a3 <- c(1.5, 2, 1, 2, 0.5, 0)
a4 <- c(2, 0.5, 0, 1, -1.5, 0.5)
cond1 <- c("A", "B", "A", "B", "A", "B")
cond2 <- c("L", "L", "H", "H", "S", "S")
df <- data.frame(cond1, cond2, a1, a2, a3, a4)
#some data munging
df <- df %>%
pivot_longer(names_to = "animal",
values_to = "FC",
cols = c(a1:a4)) %>%
mutate(across(c("cond1", "cond2", "animal"),
as.factor)) %>%
mutate(fillCol = case_when(FC < 0 ~ "decrease",
FC > 0 ~ "increase",
FC == 0 ~ "no_change"))
# plot 1
plt1 <- ggplot(df, aes(x = cond2, y = animal)) +
geom_point(aes(size = abs(FC), color = FC)) +
scale_color_gradient2(low='blue',
mid='white',
high='red',
limits=c(-2,2),
breaks=c(-2, -1, 0, 1, 2))+
facet_wrap(~cond1)
plt1
#plot 2
plt2 <- ggplot(df, aes(x = cond2, y = animal)) +
geom_point(aes(size = abs(FC), color = factor(FC))) +
facet_wrap(~cond1)
plt2
#plot 3
cols <- c("decrease" = "blue", "no_change" = "white", "increase" = "red")
plt3 <- ggplot(df, aes(x = cond2, y = animal)) +
geom_point(aes(size = abs(FC), color = fillCol)) +
scale_color_manual(name = "FC",
values = cols,
labels = c("< 0", "0", "> 0"),
guide = "legend") +
facet_wrap(~cond1)
plt3
So the result should be looking basically like plt3 but the legend should be something looking like merging those two legends in plt2. The smallest point would be zero in the middle and increasingly bigger points to negative and positive direction, with colors red = positive, blue = negative, white = zero and the labels on the legends showing the actual numbers. I was tasked with this, but I can not figure it out.
This is my first question on Stackoverflow so no images :( . I am relatively new to r.
Thank you!
Edit 12/08/2021
Per #jared_mamrot kind reply below, it only works if the values in the FC variable are somehow regular. But when I change some numbers it shows as a warning and won't show the point on plot. Is it possible to define manual scale with ranges of values or bin it somehow?
Example with changed values:
a1 <- c(-2, 2, 1.4, 0, 0.8, -0.5)
a2 <- c(-2, -2, -1.5, 2, 1, 0)
a3 <- c(1.8, 2, 1, 2, 0.6, 0.4)
a4 <- c(2, 0.2, 0, 1, -1.2, 0.5)
cond1 <- c("A", "B", "A", "B", "A", "B")
cond2 <- c("L", "L", "H", "H", "S", "S")
df <- data.frame(cond1, cond2, a1, a2, a3, a4)
df <- df %>% pivot_longer(names_to = "animal",
values_to = "FC",
cols = c(a1:a4)) %>%
mutate(across(everything(),
as.factor))
plt4 <- ggplot(df, aes(x = cond2, y = animal, color = FC, size = FC)) +
geom_point() +
scale_size_manual(values = c(10,8,6,4,3,4,6,8,10),
breaks = seq(-2, 2, 0.5),
limits = factor(seq(-2, 2, 0.5),
levels = seq(-2, 2, 0.5))) +
scale_color_manual(values = c("-2" = "#03254C",
"-1.5" = "#1167B1",
"-1" = "#187BCD",
"-0.5" = "#2A9DF4",
"0" = "white",
"0.5" = "#FAD65F",
"1" = "#F88E2A",
"1.5" = "#FC6400",
"2" = "#B72C0A"),
breaks = seq(-2, 2, 0.5),
limits = factor(seq(-2, 2, 0.5),
levels = seq(-2, 2, 0.5))) +
facet_wrap(~cond1)
plt4
> Warning message:
> Removed 7 rows containing missing values (geom_point).
The problem is that you want to map absolute values to size, and true values to color (divergent scale). I think binning the data is a great idea, but it wasn't mine, so I won't pursue this path (I encourage user Skaqqs to try an answer based on their suggestion).
I personally would prefer to keep your size as a continuous variable, thus you'd still be able to use scale_size_continuous. This requires:
separate the data into negative, positive, and "zero" values and use separate scales for your fill or color aesthetic (easy with {ggnewscale})
use absolute values for the size aesthetic
Trying to do fancy things with guides can very quickly become quite hacky. Instead of doing crazy stuff with guide functions etc, I really prefer to separate legend creation into a new plot, ("fake legend") and add the legend to the other plot (e.g., with {patchwork}).
The look / relative dimensions can obviously be changed according to your aesthetic desires, and I think easier so than when dealing with real guides.
library(tidyverse)
library(patchwork)
a1 <- c(-2, 2, 1.4, 0, 0.8, -0.5)
a2 <- c(-2, -2, -1.5, 2, 1, 0)
a3 <- c(1.8, 2, 1, 2, 0.6, 0.4)
a4 <- c(2, 0.2, 0, 1, -1.2, 0.5)
cond1 <- c("A", "B", "A", "B", "A", "B")
cond2 <- c("L", "L", "H", "H", "S", "S")
df <- data.frame(cond1, cond2, a1, a2, a3, a4)
df <-
df %>% pivot_longer(names_to = "animal", values_to = "FC", cols = c(a1:a4)) %>%
## keep your continuous variable continuous:
## make a new column which tells you what is negative and positve and zero
## turn FC into absolute values
mutate(across(-FC, as.factor),
signFC = ifelse(FC == 0, 0, sign(FC)),
FC = abs(FC))
## move data and certain aesthetics from main call to layers
## I am also using fillable points, in order to be able to show "zero" in white
p <- ggplot(mapping = aes(x = cond2, y = animal, size = FC)) +
geom_point(data = filter(df, signFC == -1), aes(fill = FC), shape = 21) +
scale_fill_fermenter(palette = "Blues", direction = 1) +
## to show negative and positives differently, but size information still
## mapped to continuous scale
ggnewscale::new_scale_fill()+
geom_point(data = filter(df, signFC == 1), aes(fill = FC), shape = 21, show.legend = FALSE) +
scale_fill_fermenter(palette = "Reds", direction = 1) +
geom_point(data = filter(df, signFC == 0), fill = "white", shape = 21) +
scale_size_continuous(limits = c(0, 2)) +
facet_wrap(~cond1) +
theme(legend.position = "none")
## When dealing with guides gets too messy, I prefer to cleanly build the legend
## as a different plot
leg_df <-
data.frame(breaks = seq(-2, 2, 0.5)) %>%
mutate(br_sign = ifelse(breaks == 0, 0, sign(breaks)),
vals = abs(breaks),
y = seq_along(vals))
## Do all the above, again :)
p_leg <-
ggplot(mapping = aes(x = 1, y = y, size = vals)) +
geom_text(data = leg_df, aes(x = 1, label = breaks, y = y), inherit.aes = FALSE,
nudge_x = .01, hjust = 0) +
geom_point(data = filter(leg_df, br_sign == -1), aes(fill = vals), shape = 21) +
scale_fill_fermenter(palette = "Blues", direction = 1) +
## to show negative and positives differently, but size information still
## mapped to continuous scale
ggnewscale::new_scale_fill()+
geom_point(data = filter(leg_df, br_sign == 1), aes(fill = vals), shape = 21, show.legend = FALSE) +
scale_fill_fermenter(palette = "Reds", direction = 1) +
geom_point(data = filter(leg_df, br_sign == 0), fill = "white", shape = 21) +
scale_size_continuous(limits = c(0, 2)) +
theme_void() +
theme(legend.position = "none",
plot.margin = margin(l = 10, r = 15, unit = "pt")) +
coord_cartesian(clip = "off")
p + p_leg + plot_layout(widths = c(1, .05))
Created on 2021-12-10 by the reprex package (v2.0.1)
One potential solution is to specify the values manually for each scale, e.g.
library(tidyverse)
a1 <- c(-2, 2, 1, 0, 0.5, -0.5)
a2 <- c(-2, -2, -1.5, 2, 1, 0)
a3 <- c(1.5, 2, 1, 2, 0.5, 0)
a4 <- c(2, 0.5, 0, 1, -1.5, 0.5)
cond1 <- c("A", "B", "A", "B", "A", "B")
cond2 <- c("L", "L", "H", "H", "S", "S")
df <- data.frame(cond1, cond2, a1, a2, a3, a4)
#some data munging
df %>%
pivot_longer(names_to = "animal",
values_to = "FC",
cols = c(a1:a4)) %>%
mutate(across(everything(),
as.factor)) %>%
ggplot(aes(x = cond2, y = animal, color = FC, size = FC)) +
geom_point() +
scale_size_manual(values = c(10,8,6,4,3,4,6,8,10),
breaks = seq(-2, 2, 0.5),
limits = factor(seq(-2, 2, 0.5),
levels = seq(-2, 2, 0.5))) +
scale_color_manual(values = c("-2" = "#03254C",
"-1.5" = "#1167B1",
"-1" = "#187BCD",
"-0.5" = "#2A9DF4",
"0" = "white",
"0.5" = "#FAD65F",
"1" = "#F88E2A",
"1.5" = "#FC6400",
"2" = "#B72C0A"),
breaks = seq(-2, 2, 0.5),
limits = factor(seq(-2, 2, 0.5),
levels = seq(-2, 2, 0.5))) +
facet_wrap(~cond1)
Created on 2021-12-08 by the reprex package (v2.0.1)
My understanding is that ggplot will automatically combine scales in the legend if the scales are defined by the same variable (FC_num), breaks, and labels. This means we don't have to use scale...manual(), which should make our code a lot more flexible and concise(!).
Here are two options:
library(ggplot2)
library(dplyr)
library(tidyr)
a1 <- c(-2, 2, 1.4, 0, 0.8, -0.5)
a2 <- c(-2, -2, -1.5, 2, 1, 0)
a3 <- c(1.8, 2, 1, 2, 0.6, 0.4)
a4 <- c(2, 0.2, 0, 1, -1.2, 0.5)
cond1 <- c("A", "B", "A", "B", "A", "B")
cond2 <- c("L", "L", "H", "H", "S", "S")
dff <- data.frame(cond1, cond2, a1, a2, a3, a4)
#some data munging
df <- dff %>%
pivot_longer(names_to = "animal",
values_to = "FC",
cols = c(a1:a4)) %>%
mutate(across(everything(),
as.factor))
# Make focal variable numeric
df$FC_num <- as.numeric(paste(df$FC))
# Define breaks based on focal variable
breaks <- seq(min(df$FC_num), max(df$FC_num), 0.5)
# Option 1
transAbs <- scales::trans_new(name="abs", transform=abs, inverse=abs)
ggplot(data=df, aes(x=cond2, y=animal, fill=FC_num, size=FC_num)) +
geom_point(pch=21) +
scale_size_continuous(range=c(3,10), trans=transAbs, breaks=breaks, labels=breaks) +
scale_fill_distiller(palette="RdBu", breaks=breaks, labels=breaks) +
guides(fill=guide_legend(reverse=TRUE), size=guide_legend(reverse=TRUE)) +
facet_wrap(~cond1)
# Option 2
ggplot(data=df, aes(x=cond2, y=animal, fill=FC_num, size=FC_num)) +
geom_point(pch=21) +
scale_size_binned_area(max_size=10, breaks=breaks, labels=breaks) +
scale_fill_distiller(palette="RdBu", breaks=breaks, labels=breaks) +
guides(fill=guide_legend(reverse=TRUE), size=guide_legend(reverse=TRUE)) +
facet_wrap(~cond1)

Plot density lines without histogram

I want to plot density lines without showing the histogram, I used this code:
hist(www, prob=TRUE, xlab = "X", main = "Plot",xlim=c(0,11), ylim=c(0,1), breaks =100)
lines(density(x, adjust=5), col="red", lwd=2)
lines(density(y, adjust=5), col="blue", lwd=2)
lines(density(z, adjust=5), col="green", lwd=2)
And the result is showing in the the picture.
How can I remove the Histogram? Thank you in advance!
You could use plot(density(...)) instead of hist:
set.seed(123)
x <- rnorm(100, 0, 1)
y <- rnorm(100, 0.5, 2)
z <- rnorm(100, 1, 1)
dens <- lapply(list(x=x, y=y, z=z), density)
ran <- apply(do.call(rbind, sapply(dens, function(i) list(data.frame(x=range(i$x), y=range(i$y))))), 2, range)
plot(dens[[1]], xlim=ran[,1], ylim=ran[,2], type = 'n', main="Density")
lapply(seq_along(dens), function(i) lines(dens[[i]], col=i))
legend("topright", names(dens), col=seq_along(dens), lty=1)
Created on 2021-01-31 by the reprex package (v1.0.0)
Even easier is plotting with the ggplot2 package:
library(ggplot2)
dat <-data.frame(group=unlist(lapply(c("x", "y", "z"), function(i) rep(i, length(get(i))))),
value=c(x, y, z))
ggplot(dat, aes(x=value, colour=group))+
geom_density()
Using three toy vectors, try this:
x <- rnorm(100, 0, 1)
y <- rnorm(100, 0.5, 2)
z <- rnorm(100, 1, 1)
plot(density(x, adjust = 5), col = "red", lwd = 2,
xlim = c(-20, 20), ylim = c(0, 0.25), xlab = "X")
par(new=T)
plot(density(y, adjust = 5), col = "blue", lwd = 2,
xlim = c(-20, 20), ylim = c(0, 0.25), xlab = "")
par(new=T)
plot(density(z, adjust = 5), col = "green", lwd = 2,
xlim = c(-20, 20), ylim = c(0, 0.25), xlab = "")
You will need to adjust xlim and ylim in the right way

My layout doesn't allow me to show xlab and ylab

It looks like something simple I am missing but have no idea how to deal with this.
So I used a layout() function and I managed to get the layout as I wanted as below picture. Iris data was used in my coding.
Problem is, it does not show me the x label and y label on the output when I use plot() functions after this. And xaxis and yaxis for plot() looks overlapping. I am not sure how to deal with this problem.
There was no problem for x and y labelling before introducing plot.new() and par() to set up the main name of my diagram. (i.e. before I use the code from plot.new() to title(), xlab and ylab were shown)
I used 6 different plots in my original code, including, the plot.new() for title(), but I omitted the rest of them for convenience
Here is my code below,
x <- iris$Sepal.Length
y <- iris$Species
x_min <- min(iris$Sepal.Length)
x_max <- max(iris$Sepal.Length)
y_min <- min(iris$Sepal.Width)
y_max <- max(iris$Sepal.Width)
layout(matrix(c(1,1,1,1,1,1,
2,2,3,3,4,4,
5,5,5,6,6,6), nc=6, byrow = TRUE), heights=c(lcm(1),1,1,1,1))
layout.show(6)
par("mar"=c(1,1,1,1,1,1))
plot.new()
plot.window(xlim=c(0,1), ylim=c(0,1))
text(x=0.5,y=0.5,"scatter and density plots for Sepal and Length and Sepal Width" ,font=2, cex=1.5)
plot(...)
You can use the xlab and ylab arguments in title. However, the way you have constructed the plot means that when you reset par at the end, these are drawn off the page due ti their position relative to your custom axis. If you simply leave par alone, you get:
den1 = density(CDE1$V1)
den2 = density(CDE1$V2)
col1 = hsv(h = 0.65, s = 0.6, v = 0.8, alpha = 0.5)
col2 = hsv(h = 0.85, s = 0.6, v = 0.8, alpha = 0.5)
plot.new()
plot.window(xlim = c(25,65), ylim = c(0, 0.14))
axis(side = 1, pos = 0, at = seq(from = 25, to = 65, by = 5), col = "gray20",
lwd.ticks = 0.25, cex.axis = 1, col.axis = "gray20", lwd = 1.5)
axis(side = 2, pos = 25, at = seq(from = 0, to = 0.14, by = 0.02),
col = "gray20", las = 2, lwd.ticks = 0.5, cex.axis = 1,
col.axis = "gray20", lwd = 1.5)
polygon(den1$x, den1$y, col = col1, border ="black",lwd = 2)
polygon(den2$x, den2$y, col = col2, border ="black",lwd = 2)
text(52, 0.10, labels ="CDET", col =col1, cex = 1.25,font=2)
text(35, 0.03, labels ="SDFT", col =col2, cex = 1.25,font=2)
title(main = "Gestational Day 100/283",
xlab = "Fibril Diameter (nm)",
ylab = "density")
Of course, you could get a similar plot with less code and much easier adjustments using ggplot:
library(ggplot2)
ggplot(tidyr::pivot_longer(CDE1, 1:2), aes(value, fill = name)) +
geom_density() +
scale_fill_manual(values = c(col1, col2), labels = c("CDET", "SDFT")) +
scale_x_continuous(breaks = seq(25, 65, 5), limits = c(25, 65)) +
scale_y_continuous(breaks = seq(0, 0.14, 0.02), limits = c(0, 0.14)) +
theme_classic(base_size = 16) +
labs(title = "Gestational Day 100/283", x = "Fibril Diameter (nm)",
fill = NULL) +
theme(plot.title = element_text(hjust = 0.5))
Data used
Obviously, we don't have your data, so I had to create a reproducible approximation:
set.seed(123)
CDE1 <- data.frame(V1 = rnorm(20, 47.5, 4), V2 = rnorm(20, 44, 5))

How to show sample error bars in the legend in R?

I'm plotting data with colored error bars in R. I'd like to show "sample error bars" (with the colour used in the plot) in the legend, but how?
library("Hmisc")
d1=data.frame(x=c(1,2,3,4,5), meanY=c(1,2,3,4,5), sdY=c(1,1,1,1,1))
d2=data.frame(x=c(1,2,3,4,5), meanY=c(2.1,3.3,4.1,5.2,6.1), sdY=c(1.3,1.2,1.4,1.1,1.2))
plot(1, 1, type="n", xlab="X values", ylab="Y values", xlim=c(1,5), ylim=c(0,7))
with ( data = d1, expr = Hmisc::errbar(x, meanY, meanY+sdY, meanY-sdY, pch=1, cex=.5, cap=.0025, add=T, errbar.col="red") )
with ( data = d2, expr = Hmisc::errbar(x, meanY, meanY+sdY, meanY-sdY, pch=1, cex=.5, cap=.0025, add=T, errbar.col="green") )
legend(x="bottomright", legend=c("d1", "d2"), pch=1, pt.cex=.5)
Somewhat manual build of legend...
# bind data together to simplify plot code
df <- rbind(d1, d2)
# plot
with(df,
errbar(x = x + c(rep(0.05, nrow(d1)), rep(-0.05, nrow(d2)), # dodge points to avoid overplotting
y = meanY,
yplus = meanY + sdY,
yminus = meanY - sdY,
pch = 1, cex = 0.5, cap = .0025,
errbar.col = rep(c("red", "green"), times = c(nrow(d1), nrow(d2))),
xlab = "X values", ylab = "Y values",
xlim = c(1, 5), ylim = c(0, 7)))
# create data for legend
df_legend <- data.frame(x <- c(4.5, 4.5),
y <- c(1, 2),
sdy <- c(0.3, 0.3))
# add symbols to legend
with(df_legend,
errbar(x = x,
y = y,
yplus = y + sdy,
yminus = y - sdy,
pch = 1, cex =.5, cap = .0025,
errbar.col = c("red", "green"),
add = TRUE))
# add text to legend
with(df_legend,
text(x = x + 0.2,
y = y,
labels = c("d2", "d1")))
# add box
with(df_legend,
rect(xleft = x - 0.2,
ybottom = y[1] - 0.5,
xright = x + 0.4,
ytop = y[2] + 0.5))

Resources