This repository contains a collection of introduction slides and bioinf tutorials.
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

##################################
# 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