Content
- Foundations: parameters
- Panels
- Annotations
- Layered plot
- Custom axis
- Custom colors
Ziyi Li (ziyi.li@emory.edu)
par
function is used to specific global graphics parameters that affect all plots in an R session. These parameters can often be overriden as arguments to specific plotting functions.pch
: the plotting symbol (default is open circle)par("pch")
## [1] 1
lty
: the line type (default is solid line), can be dashed, dotted, etc.par("lty")
## [1] "solid"
par(mfrow = c(4,1), mar=c(1,2.1,1,1) )
x = 1:5
y = 1:5
plot(x, y, lty = 1, main = "lty = 1", type="l")
plot(x, y, lty = 2, main = "lty = 1", type="l")
plot(x, y, lty = 3, main = "lty = 1", type="l")
plot(x, y, lty = 4, main = "lty = 1", type="l")
lwd
: the line width, specified as an integer multiplepar("lwd")
## [1] 1
par(mfrow = c(4,1), mar=c(1,2.1,1,1))
plot(x, y, lwd = 0.5, main = "lwd = 0.5", type="l")
plot(x, y, lwd = 1, main = "lwd = 1", type="l")
plot(x, y, lwd = 3, main = "lwd = 3", type="l")
plot(x, y, lwd = 5, main = "lwd = 5", type="l")
col
: the plotting color specified as a number, string, or hex code; The colors function gives you a vector of colors by namepar("col")
## [1] "black"
par(mfrow = c(4,1), mar=c(1,2.1,1,1))
plot(x, y, col = 1, main = "col = 1", type="l")
plot(x, y, col = 2, main = "col = 2", type="l")
plot(x, y, col = 3, main = "col = 3", type="l")
plot(x, y, col = 4, main = "col = 4", type="l")
bg
: the background colorpar("bg")
## [1] "white"
par(mfrow = c(2,1), bg="pink", mar=c(1,2.1,1,1))
x = 1:10
y = rnorm(10)
plot(x, y, col = 1, main = "col = 1")
plot(x, y, col = 2, main = "col = 2")
mar
: the margins<ref: http://rgraphics.limnology.wisc.edu/rmargins_sf.php>
par("mar")
## [1] 5.1 4.1 4.1 2.1
x = 1:10
y = rnorm(10)
plot(x, y)
par(mar = c(0.5,0.5,0.5,0.5))
plot(x, y)
How can I get two plots to be on the same page ?
par(mfrow=c(1,2)) # One row and two columns
plot(mtcars$mpg, main="MPG", type="l", xlab="Car Number",ylab="MPG")
plot(mtcars$mpg, main="MPG", type="b", xlab="Car Number",ylab="MPG")
par(mfrow=c(2,2)) # Two rows and two columns
plot(mtcars$mpg,main="MPG",xlab="Car",ylab="MPG",type="p")
plot(mtcars$mpg,main="MPG",xlab="Car",ylab="MPG",type="l")
plot(mtcars$mpg,main="MPG",xlab="Car",ylab="MPG",type="h")
plot(mtcars$mpg,main="MPG",xlab="Car",ylab="MPG",type="o")
legend("topleft",legend=c("Test Legend"),cex=0.8)
We usually take this approach when we want to plot data across different categories. Like the mpg vs weight across cylinder types. We have three unique cylinder values:
unique(mtcars$cyl) # We have three categories so create 3 plots
## [1] 6 4 8
par(mfrow=c(1,3)) # One row and three columns
fourcyl <- mtcars[mtcars$cyl == 4,]
sixcyl <- mtcars[mtcars$cyl == 6,]
eightcyl <- mtcars[mtcars$cyl == 8,]
plot(fourcyl$wt, fourcyl$mpg, main = "MPG vs Wt 4 Cyl", ylim=c(0,40))
plot(sixcyl$wt, sixcyl$mpg, main = "MPG vs Wt 6 Cyl", ylim=c(0,40))
plot(eightcyl$wt, eightcyl$mpg, main = "MPG vs Wt 8 Cyl", ylim=c(0,40))
par(mfrow=c(1,1)) # Reset the plot window
par(mfrow=c(1,2)) # One row and three columns
fourcyl <- mtcars[mtcars$cyl == 4,]
plot(fourcyl$wt, fourcyl$mpg, main = "MPG vs Wt 4 Cyl", ylim=c(0,40),
xlab = "my wt", ylab = "my mpg")
legend("bottomright", inset=0.05, "This is data", pch=1, col="black")
plot(fourcyl$wt, fourcyl$mpg, main = "MPG vs Wt 4 Cyl", ylim=c(0,40),
xlab = "my wt", ylab = "my mpg")
legend("bottomright", "This is data", pch=1, col="black")
We could put up our own grid using some “primitive” graphics functions:
plot(mtcars$wt, mtcars$mpg, xlab = "Weight / 1,000", main = "MPG vs. WT")
# Draws vertical dashed lines at 2,3,4,5
abline(v=c(2,3,4,5),lty=2,col="gray90")
# Draws horizontal dashed lines at 10,15,20,25,30
abline(h=c(10,15,20,25,30), lty=2, col="gray90")
We can also add text to our plot with no problem.
plot(mtcars$wt, mtcars$mpg, main="Mileage vs. Car Weight",
xlab="Weight", ylab="Mileage", pch=18, col="blue")
text(mtcars$wt, mtcars$mpg, # We cannot use the formula in text
row.names(mtcars), # Get the row names
cex=0.6, # Scaling of the font size
pos=4, # 1=below, 2=left, 3=above, 4=right
col="red")
The text label is too long. We can shorten them:
plot(mtcars$wt, mtcars$mpg, main="Mileage vs. Car Weight",
xlab="Weight", ylab="Mileage", pch=18, col="blue")
carlabs <- sapply(strsplit(row.names(mtcars)," "),
function(x) x[[1]])
text(mtcars$wt, mtcars$mpg, # Note we cannot use the formula in text
carlabs, # Get the row names
cex=0.6, # Scaling of the font size
pos=4, # 1=below, 2=left, 3=above, 4=right
col="red")
Let’s look at a more involved annotation example. We’ll use the same data:
plot(mtcars$mpg ~ mtcars$wt,cex=0.8, pch=21,col="blue",bg="red",
xlab="Wt in Lbs/1,000", ylab="Miles Per Gallon")
title(main="The mtcars data set wt vs. MPG")
# Next draw a vertical line at the mean of the weight
abline(v=mean(mtcars$wt),lty=2,col="blue")
# Next draw a horizontal line at the man of the MPG
abline(h=mean(mtcars$mpg),lty=2,col="blue")
points(mean(mtcars$wt), # Draws a diamond at the common mean
mean(mtcars$mpg),
pch=23,col="black",
bg="brown", cex=2)
# Let's put some custom text on the graph to indicate the mean.
text(mean(mtcars$wt),min(mtcars$mpg),
paste("Mean:",round(mean(mtcars$wt),2)),pos=4)
text(min(mtcars$wt),mean(mtcars$mpg),
paste("Mean:",round(mean(mtcars$mpg),2)),adj=c(0,1))
We could also use information from a data frame to help us print different characters based on value. Like in mtcars. Let’s plot MPG vs Weight but pick a different plot character based on Transmission Type. Here is one way to do it:
# A null plot
plot(mtcars$wt, mtcars$mpg, type="n", main="MPG vs. Weight")
auto <- mtcars[mtcars$am == 0,]
manu <- mtcars[mtcars$am == 1,]
points(auto$wt, auto$mpg, pch = 0)
points(manu$wt, manu$mpg, pch = 1)
legend("topright", inset=0.05, c("manual","auto"), pch = c(1,0))
An easier way is
# A null plot
mtcars$am
## [1] 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 1 1 1 1
# We see that am is 0 or 1 which just
# so happen to also represent
# valid print characters
plot(mtcars$wt, mtcars$mpg, pch=mtcars$am, main="MPG vs. Weight", sub="Different plot chars")
legend("topright", inset=0.05, c("manual","auto"), pch = unique(mtcars$am))
It is also possible to build a plot in layers. We initialize a “blank” plot using the plot command but we specify a type of “n”.
Let’s plot wt vs MPG and do it such that the records with a weight below the mean weight are in red and those above the mean weight are in blue
plot(mtcars$wt,mtcars$mpg,type="n", xlab="Weight in lbs/1,000",
ylab="MPG", main="MPG vs. Weight")
How is this useful ? Well we can add points or lines in stages. This allows us to plot things on an existing plot using specific colors or print characters.
plot(mtcars$wt,mtcars$mpg,type="n",xlab="Weight in lbs/1,000",
ylab="MPG", main="MPG vs. Weight")
# Let's get records for each category
above.mean <- mtcars[mtcars$wt >= mean(mtcars$wt),]
below.mean <- mtcars[mtcars$wt < mean(mtcars$wt),]
# Use the points command to plot each group
points(below.mean$wt,below.mean$mpg,col="red")
points(above.mean$wt,above.mean$mpg,col="blue")
# Draw a vertical line where the mean(wt) is
abline(v=mean(mtcars$wt),lty=2,col="gray90")
Sometimes we want to draw an axis ourselves because R’s defaults aren’t what we want. Imagine a set of observations over time such as stock market activity.
Here is a data frame you can read in that tracks actual stock market performance for Microsoft, (MSFT), for each trading day of the year 2014.
url <- "https://www.dropbox.com/s/kkohm0vcgzbj136/stock.data.14.csv?dl=1"
msft <- read.csv(url)
head(msft)
## Date Open High Low Close Volume Adj.Close
## 1 2014-01-02 37.35 37.40 37.10 37.16 30632200 36.17
## 2 2014-01-03 37.20 37.22 36.60 36.91 31134800 35.93
## 3 2014-01-06 36.85 36.89 36.11 36.13 43603700 35.17
## 4 2014-01-07 36.33 36.49 36.21 36.41 35802800 35.44
## 5 2014-01-08 36.00 36.14 35.58 35.76 59971700 34.81
## 6 2014-01-09 35.88 35.91 35.40 35.53 36516300 34.58
plot(msft$High,type="l",main="High MSFT Price", xlab="Day of Year",ylab="Price in $")
mtext("2014",3)
The day number is okay but we could also the actual dates as labels. But that could be a problem. First, we use the xaxt argument to suppress the printing of the x-axis
plot(msft$High,type="l",main="High MSFT Price",
xlab="Day of Year",ylab="Price in $", xaxt="n")
axis(1,at=1:nrow(msft),labels=msft$Date)
That wasn’t so good because the X-axis got really crowded. We can print labels for the x-axis every 30 days or so using this approach. We could alter this to accommodate an arbitrary number of days and labels. Notice how we generate sequence that we then use to index into the Dates.
plot(msft$High,type="l", main="High MSFT Price",
xlab="Day of Year",ylab="Price in $", xaxt="n")
mtext("2014",3)
dseq <- seq(1,nrow(msft),30)
axislabs <- substr(msft$Date[dseq],6,10)
axis(1, at=dseq, labels=axislabs, cex.axis=0.8)
length(colors()) # The colors function returns a vector of colors
## [1] 657
colors()[1:5]
## [1] "white" "aliceblue" "antiquewhite" "antiquewhite1"
## [5] "antiquewhite2"
grep("yellow",colors(),value=TRUE)
## [1] "greenyellow" "lightgoldenrodyellow" "lightyellow"
## [4] "lightyellow1" "lightyellow2" "lightyellow3"
## [7] "lightyellow4" "yellow" "yellow1"
## [10] "yellow2" "yellow3" "yellow4"
## [13] "yellowgreen"
grep("purple",colors(),value=TRUE)
## [1] "mediumpurple" "mediumpurple1" "mediumpurple2" "mediumpurple3"
## [5] "mediumpurple4" "purple" "purple1" "purple2"
## [9] "purple3" "purple4"
Strongly recommend R color cheatsheet.
library("colorspace")
## Warning: package 'colorspace' was built under R version 3.5.2
par(mfrow = c(1,2))
plot_it <- function(cols){
y <- sort(runif(500,0,10))
x <- rep(1:5, each=100) + rnorm(500,0,0.5)
x_ind <- rep(1:5, each=100)
plot(x, y, pch = 19, col = cols[x_ind])
}
mycols <- rainbow_hcl(5)
plot_it(mycols)
mycols <- heat_hcl(5)
plot_it(mycols)