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 xaxis label 

title(xlab = "xaxis") 

require(dlfUtils) 

par(xpd = NA) 

text( 

2, 

line2user(3, 1), # get y location for 3rd margin line in user coordinates 

"xaxis" 

) 





### 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.datatoviz.com/caveats.html 

# https://rgraphgallery.com/allgraphs.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 multipage 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 (multipanel plots) 

# for loops in combination with if statements 

# apply (sapply, lapply) functions 

# map function in tidyverse


