You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
346 lines
7.9 KiB
346 lines
7.9 KiB
################################## |
|
# workshop: Plot()-ing in base R # |
|
################################## |
|
|
|
|
|
### basic plotting elements #### |
|
|
|
# open new plot |
|
dev.off() |
|
par(mar = c(4, 4, 1, 1), ann = F) |
|
|
|
# generate empty plot |
|
plot( |
|
0, # x |
|
0, # y |
|
type = "n", # don't plot anything |
|
ylim = c(-0.5, 1.5), # y dimensions |
|
xlim = c(0, 1), # x dimensions |
|
axes = F # don't show axes |
|
) |
|
|
|
# get plot dimensions in user coordinates |
|
par("usr") |
|
|
|
# individual data points, requires x and y coordinates |
|
points( |
|
x = seq(0, 1, 0.1), |
|
y = seq(0, 1, 0.1), |
|
pch = 16, # point character, i.e. symbol |
|
cex = seq(0.5, 2, length.out = 11), # point size |
|
col = rainbow(11) # point color |
|
) |
|
|
|
# individual text labels (e.g. for data points), requires x and y coordinates |
|
text( |
|
x = seq(0, 1, 0.1), |
|
y = seq(0, 1, 0.1), |
|
labels = LETTERS[1:11], |
|
pos = c(rep(3, 5), rep(1, 6)) # position of label relative to xy (1: below; 2: left; 3: top; 4:right) |
|
) |
|
text( |
|
0.5, # x |
|
0.8, # y |
|
labels = "value without point", |
|
font = 2 # bold text |
|
) |
|
|
|
# connect individual data points (in the order of input), requires x and y coordinates |
|
lines( |
|
x = seq(0, 1, 0.1), |
|
y = seq(0, 1, 0.1), |
|
lty = 3, # line type dashed |
|
lwd = 3 # line width |
|
) |
|
lines( |
|
x = seq(0, 1, length.out = 10), |
|
y = rep(c(0.1, 0.3), 5), |
|
lty = 1, # line type solid |
|
lwd = 1 # line width |
|
) |
|
|
|
# line connectors between 2 points, requires start and end x and y coordinates |
|
segments( |
|
x0 = seq(0, 1, 0.1), |
|
y0 = seq(0, 1, 0.1) - 0.2, |
|
x1 = seq(0, 1, 0.1), |
|
y1 = seq(0, 1, 0.1) + 0.2 |
|
) |
|
|
|
# rectangular box, requires x and y coordinates of lower left and upper right hand corner |
|
rect( |
|
xleft = 0.3, |
|
ybottom = 0.75, |
|
xright = 0.7, |
|
ytop = 0.85, |
|
border = "red", |
|
lty = 2, |
|
lwd = 2, |
|
col = "yellow" |
|
) |
|
|
|
# connect individual data points (in the order of input) to form a polygon (fill optional), |
|
# requires x and y coordinates (order is important: lines should not cross) |
|
# similar to lines() |
|
polygon( |
|
x = c(0, 0.2, 0.2, 0.3, 0.2, 0.2, 0), |
|
y = c(0.75, 0.75, 0.7, 0.8, 0.9, 0.85, 0.85), |
|
col = "red" |
|
) |
|
|
|
# like segments, but with arrow head |
|
arrows( |
|
x0 = rep(0, 3), |
|
y0 = rep(0, 3), |
|
x1 = c(0.5, 0.6, 0.7), |
|
y1 = c(0.1, 0.2, 0.3), |
|
length = 0.1 # length of arrowhead |
|
) |
|
|
|
# draw box (rectangle) around plotting area (defined by user coordinates) |
|
box("plot", lwd = 0.5) |
|
|
|
# add axis to plot |
|
# specify which side of plot to add axis |
|
axis( |
|
side = 2, |
|
mgp = c(2, 0.7, 0), # position of axis label, tick labels and axis line (in margin lines) |
|
las = 1 # always horizontal |
|
) |
|
axis( |
|
side = 1, |
|
mgp = c(2, 0.7, 0), |
|
at = c(0.2, 0.5, 0.8), # specify position of ticks |
|
labels = c("small", "medium", "large") |
|
) |
|
|
|
# add text labels on margin |
|
mtext( |
|
text = "Size", |
|
side = 1, # side of plot (underneath) |
|
line = 2 # margin line |
|
) |
|
|
|
# also works with |
|
title(ylab = "value") |
|
# for another example, move the label closer to the axis |
|
par(mgp = c(2, 1, 0)) |
|
# yes, you can use sub- abd superscript in R ;) |
|
title(ylab = expression("NH"[4]^" +"*" concentration [micro mol L"^-1*"]")) |
|
|
|
# add line to plot, |
|
# e.g. linear fit, horizontal or vertical lines with specific intersection with axis |
|
abline(a = 0.2, b = 0.5, col = "blue", lwd = 2) # intercept and slope |
|
abline(h = 0.5, col = "blue", lwd = 2) |
|
abline(v = 0.85, col = "blue", lwd = 2) |
|
# par(xpd = NA) # this way the line will also be visible outside the plotting area |
|
# abline(v = 0.85, col = "blue", lwd = 2) |
|
|
|
# extract coefficients from linear model |
|
x <- seq(0, 1, 0.1) |
|
y <- rnorm(11, mean = 0.5, sd = 0.2) |
|
mod <- lm(y ~ x) |
|
abline(mod, col = "red") |
|
points(x, y, pch = 16, col = "red") |
|
# show equation in plot |
|
mod$coefficients |
|
text( |
|
par("usr")[1], |
|
par("usr")[4] - (par("usr")[4] - par("usr")[3]) * 0.05, |
|
pos = 4, |
|
labels = paste0("y = ", round(mod$coefficients[2], 2), " x + ", round(mod$coefficients[1], 2)) |
|
) |
|
# show confidence interval |
|
conf_mod <- predict(mod, interval="confidence", level = 0.95) |
|
polygon( |
|
c(x, rev(x)), |
|
c(conf_mod[, "lwr"], rev(conf_mod[, "upr"])), |
|
border = NA, |
|
col = adjustcolor("red", alpha.f = 0.2) |
|
) |
|
|
|
# add legend to plot |
|
legend( |
|
"topright", # specific coordinates can also be given (as in rect) |
|
legend = c(LETTERS[1:4]), # just some dummy text, |
|
col = 1:4, |
|
pch = 15, |
|
ncol = 2, |
|
title = "legend", |
|
pt.cex = 2 |
|
) |
|
|
|
|
|
### subplots #### |
|
|
|
# define what should be plotted |
|
myplot <- function() { |
|
plot(x, y, pch = 16, col = "red", axes = F) |
|
abline(mod, col = "red") |
|
polygon( |
|
c(x, rev(x)), |
|
c(conf_mod[, "lwr"], rev(conf_mod[, "upr"])), |
|
border = NA, |
|
col = adjustcolor("red", alpha.f = 0.2) |
|
) |
|
} |
|
|
|
# add subplot at specific coordinates |
|
require(Hmisc) |
|
subplot( |
|
myplot(), |
|
x = c(-0.04, 0.3), # x coordinates for lower left and upper right corner of subplot |
|
y = c(-0.58, -0.2), # y coordinates for lower left and upper right corner of subplot |
|
pars = list(mar = c(0, 0, 0, 0), ann = F) # list of plotting parameters for subplot |
|
) |
|
# scale based on user coordinates |
|
subplot( |
|
myplot(), |
|
x = c(par("usr")[1], par("usr")[1] + (par("usr")[2] - par("usr")[1]) * 0.3), |
|
y = c(par("usr")[3], par("usr")[3] + (par("usr")[4] - par("usr")[3]) * 0.3), |
|
pars = list(mar = c(0, 0, 0, 0), ann = F) |
|
) |
|
|
|
# draw border around subplot |
|
rect( |
|
-0.04, -0.58, 0.3, -0.2, |
|
col = NA, |
|
border = "black", |
|
lwd = 0.5 |
|
) |
|
|
|
# other example: pie chart |
|
myplot <- function() { |
|
pie(1:4, labels = NA) |
|
} |
|
# providing center position of subplot |
|
subplot( |
|
myplot(), |
|
x = 0.7, |
|
y = -0.2, |
|
size = c(2, 2), # size of subplot along both dimensions |
|
pars = list(mar = c(0, 0, 0, 0), ann = F) |
|
) |
|
# alternatively, look into pieGlyph or the bioconductor package Rgraphviz |
|
|
|
|
|
### image #### |
|
|
|
# useful for any kind of heatmap |
|
dat <- matrix(rnorm(100), 10, 10) |
|
par(ann = F) |
|
image( |
|
dat, |
|
x = 1:10, |
|
y = 1:10 |
|
) |
|
# symmetric color encoding |
|
image( |
|
dat, # matrix with values to show as colors |
|
x = 1:10, # x position for each 'pixel' |
|
y = 1:10, # y position for each 'pixel' |
|
zlim = c(-max(abs(dat)), max(abs(dat))), # lower and upper bound for color scale |
|
col = colorRampPalette(c("blue", "white", "red"))(50) |
|
) |
|
|
|
# plotting on margins |
|
# e.g. customize position of x-axis label |
|
title(xlab = "x-axis") |
|
require(dlfUtils) |
|
par(xpd = NA) |
|
text( |
|
2, |
|
line2user(3, 1), # get y location for 3rd margin line in user coordinates |
|
"x-axis" |
|
) |
|
|
|
|
|
### layout function usage #### |
|
|
|
# more versatile plot arrangements |
|
layout( |
|
mat = matrix( |
|
c(1, 1, 1, |
|
2, 2, 3, |
|
4, 5, 6), |
|
nrow = 3, |
|
ncol = 3, |
|
byrow = T |
|
), |
|
widths = c(1, 1, 0.5), |
|
heights = c(1.3, 1, 1) |
|
) |
|
# this will produce a the following multipanel plot |
|
# 6 plots in 3 rows |
|
# row 1: first plot over full width of plotting device and one third as high as the others |
|
# row 2: second and third plot, the second taking up 4 times as much space as the third |
|
# row 3: the last 3 plots, with plot 4 and 5 each taking up twice as much space as plot 6 |
|
|
|
# Let's have a look: |
|
# use smaller margins |
|
par(mar = c(1, 1, 1, 1)) |
|
for(i in 1:6) { |
|
plot.new() |
|
box("plot") |
|
} |
|
|
|
|
|
### ready made plotting functions #### |
|
|
|
# below is a small selection of plotting functions already tailored to a specific purpose |
|
?boxplot |
|
?barplot |
|
?pie |
|
?hist |
|
?image |
|
?maps::map |
|
?fmsb::radarchart |
|
?vioplot::vioplot |
|
?UpSetR::upset |
|
?venn::venn |
|
|
|
# I won't reinvent the wheel here. Have a look at: |
|
# https://www.data-to-viz.com/caveats.html |
|
# https://r-graph-gallery.com/all-graphs.html |
|
|
|
|
|
### export figure to file #### |
|
|
|
# to save as pdf, run this before starting plot |
|
pdf("figure.pdf", width = 7, height = 9) # device dimensions are in inches (A4) |
|
# your plottin code |
|
# close with |
|
dev.off() |
|
# multiple plots can be added to a multi-page pdf with the argument 'onefile = T' |
|
|
|
# to save as image |
|
?png |
|
?tiff |
|
?jpeg |
|
|
|
|
|
### Getting your data into shape #### |
|
|
|
# square brackets and/or the dollar sign to navigate and subset R objects |
|
|
|
# base R solutions |
|
by() |
|
aggregate() |
|
melt() |
|
cast() |
|
order() |
|
all.equal() |
|
match() |
|
table() |
|
cumsum() |
|
scales::rescale() |
|
|
|
# tidyverse solutions: |
|
filter() |
|
group_by() |
|
summarise() |
|
|
|
# multiple data sets (multi-panel plots) |
|
# for loops in combination with if statements |
|
# apply (sapply, lapply) functions |
|
# map function in tidyverse
|
|
|