Chapter 4.1.1 Exercises
In [1]:
require(grDevices) # for colours
tN <- table(Ni <- stats::rpois(100, lambda = 5)); tN
r <- barplot(tN, col = rainbow(20))
In [1]:
require(graphics)
# A Color Wheel
pie(rep(1, 12), col = rainbow(12))
In [2]:
#------ Some palettes ------------
demo.pal <-
function(n, border = if (n < 32) "light gray" else NA,
main = paste("color palettes; n=", n),
ch.col = c("rainbow(n, start=.7, end=.1)", "heat.colors(n)",
"terrain.colors(n)", "topo.colors(n)",
"cm.colors(n)"))
{
nt <- length(ch.col)
i <- 1:n; j <- n / nt; d <- j/6; dy <- 2*d
plot(i, i+d, type = "n", yaxt = "n", ylab = "", main = main)
for (k in 1:nt) {
rect(i-.5, (k-1)*j+ dy, i+.4, k*j,
col = eval(parse(text = ch.col[k])), border = border)
text(2*j, k * j + dy/4, ch.col[k])
}
}
n <- if(.Device == "postscript") 64 else 16
# Since for screen, larger n may give color allocation problem
demo.pal(n)
In [1]:
# Let’s create a pirateplot of the ChickWeight data. I’ll set the dependent variable to weight, and the independent variable to Time using the argument formula = weight ~ Time:
yarrr::pirateplot(formula = weight ~ Time, # dv is weight, iv is Diet
data = ChickWeight,
main = "Pirateplot of chicken weights",
xlab = "Diet",
ylab = "Weight")
In [7]:
# There are many different pirateplot themes, these themes dictate the overall look of the plot. To specify a theme, just use the theme = x argument, where x is the theme number:
yarrr::pirateplot(formula = weight ~ Diet, # dv is weight, iv is Diet
data = ChickWeight,
theme = 1,
main = "Pirateplot of chicken weights",
xlab = "Diet",
ylab = "Weight")
In [10]:
library(yarrr)
# For example, here is a pirateplot height data from the pirates dataframe using theme = 3. Here, I’ll plot pirates’ heights as a function of their sex and whether or not they wear a headband. I’ll also make the plot all grayscale by using the pal = "gray" argument:
yarrr::pirateplot(formula = height ~ sex + headband, # DV = height, IV1 = sex, IV2 = headband
data = pirates,
theme = 3,
main = "Pirate Heights",
pal = "gray")
In [11]:
# For example, I could create the following pirateplots using theme = 0 and specifying elements explicitly:
pirateplot(formula = weight ~ Time,
data = ChickWeight,
theme = 0,
main = "Fully customized pirateplot",
pal = "southpark", # southpark color palette
bean.f.o = .6, # Bean fill
point.o = .3, # Points
inf.f.o = .7, # Inference fill
inf.b.o = .8, # Inference border
avg.line.o = 1, # Average line
bar.f.o = .5, # Bar
inf.f.col = "white", # Inf fill col
inf.b.col = "black", # Inf border col
avg.line.col = "black", # avg line col
bar.f.col = gray(.8), # bar filling color
point.pch = 21,
point.bg = "white",
point.col = "black",
point.cex = .7)
In [12]:
# If you don’t want to start from scratch, you can also start with a theme, and then make selective adjustments:
pirateplot(formula = weight ~ Time,
data = ChickWeight,
main = "Adjusting an existing theme",
theme = 2, # Start with theme 2
inf.f.o = 0, # Turn off inf fill
inf.b.o = 0, # Turn off inf border
point.o = .2, # Turn up points
bar.f.o = .5, # Turn up bars
bean.f.o = .4, # Light bean filling
bean.b.o = .2, # Light bean border
avg.line.o = 0, # Turn off average line
point.col = "black") # Black points
In [13]:
# Just to drive the point home, as a barplot is a special case of a pirateplot, you can even reduce a pirateplot into a horrible barplot:
# Reducing a pirateplot to a (at least colorful) barplot
pirateplot(formula = weight ~ Diet,
data = ChickWeight,
main = "Reducing a pirateplot to a (horrible) barplot",
theme = 0, # Start from scratch
pal = "black",
inf.disp = "line", # Use a line for inference
inf.f.o = 1, # Turn up inference opacity
inf.f.col = "black", # Set inference line color
bar.f.o = .3)
In [14]:
# Additional pirateplot customizations
pirateplot(formula = weight ~ Diet,
data = ChickWeight,
main = "Adding quantile lines and background colors",
theme = 2,
cap.beans = TRUE,
back.col = transparent("blue", .95), # Add light blue background
gl.col = "gray", # Gray gridlines
gl.lwd = c(.75, 0),
inf.f.o = .6, # Turn up inf filling
inf.disp = "bean", # Wrap inference around bean
bean.b.o = .4, # Turn down bean borders
quant = c(.1, .9), # 10th and 90th quantiles
quant.col = "black") # Black quantile lines
In [15]:
# If you include the plot = FALSE argument to a pirateplot, the function will return some values associated with each bean in the plot. In the next chunk, I’ll create a pirateplot
pirateplot(formula = tattoos ~ sex + headband,
data = pirates)
In [16]:
# Save data from the pirateplot to an object
tattoos.pp <- pirateplot(formula = tattoos ~ sex + headband,
data = pirates,
plot = FALSE)
In [17]:
# Now I can access the summary and inferential statistics from the plot in the tattoos.pp object. The most interesting element is $summary which shows summary statistics for each bean (aka, group):
# Show me statistics from groups in the pirateplot
tattoos.pp
# Once you’ve created a plot with a high-level plotting function, you can add additional elements with low-level functions. For example, you can add data points with points(), reference lines with abline(), text with text(), and legends with legend().
In [25]:
library(ggplot2)
ggplot(data = mpg) +
geom_point(mapping = aes(x = displ, y = hwy)) +
facet_grid(drv ~ cyl)
In [1]:
require(stats) # for rnorm
plot(-4:4, -4:4, type = "n") # setting up coord. system
points(rnorm(200), rnorm(200), col = "red")
points(rnorm(100)/2, rnorm(100)/2, col = "blue", cex = 1.5)
In [2]:
op <- par(bg = "light blue")
x <- seq(0, 2*pi, len = 51)
## something "between type='b' and type='o'":
plot(x, sin(x), type = "o", pch = 21, bg = par("bg"), col = "blue", cex = .6,
main = 'plot(..., type="o", pch=21, bg=par("bg"))')
par(op)
In [3]:
## Not run:
## The figure was produced by calls like
png("pch.png", height = 0.7, width = 7, res = 100, units = "in")
par(mar = rep(0,4))
plot(c(-1, 26), 0:1, type = "n", axes = FALSE)
text(0:25, 0.6, 0:25, cex = 0.5)
points(0:25, rep(0.3, 26), pch = 0:25, bg = "grey")
## End(Not run)
In [4]:
##-------- Showing all the extra & some char graphics symbols ---------
pchShow <-
function(extras = c("*",".", "o","O","0","+","-","|","%","#"),
cex = 3, ## good for both .Device=="postscript" and "x11"
col = "red3", bg = "gold", coltext = "brown", cextext = 1.2,
main = paste("plot symbols : points (... pch = *, cex =",
cex,")"))
{
nex <- length(extras)
np <- 26 + nex
ipch <- 0:(np-1)
k <- floor(sqrt(np))
dd <- c(-1,1)/2
rx <- dd + range(ix <- ipch %/% k)
ry <- dd + range(iy <- 3 + (k-1)- ipch %% k)
pch <- as.list(ipch) # list with integers & strings
if(nex > 0) pch[26+ 1:nex] <- as.list(extras)
plot(rx, ry, type = "n", axes = FALSE, xlab = "", ylab = "", main = main)
abline(v = ix, h = iy, col = "lightgray", lty = "dotted")
for(i in 1:np) {
pc <- pch[[i]]
## 'col' symbols with a 'bg'-colored interior (where available) :
points(ix[i], iy[i], pch = pc, col = col, bg = bg, cex = cex)
if(cextext > 0)
text(ix[i] - 0.3, iy[i], pc, col = coltext, cex = cextext)
}
}
pchShow()
pchShow(c("o","O","0"), cex = 2.5)
pchShow(NULL, cex = 4, cextext = 0, main = NULL)
In [5]:
## ------------ test code for various pch specifications -------------
# Try this in various font families (including Hershey)
# and locales. Use sign = -1 asserts we want Latin-1.
# Standard cases in a MBCS locale will not plot the top half.
TestChars <- function(sign = 1, font = 1, ...)
{
MB <- l10n_info()$MBCS
r <- if(font == 5) { sign <- 1; c(32:126, 160:254)
} else if(MB) 32:126 else 32:255
if (sign == -1) r <- c(32:126, 160:255)
par(pty = "s")
plot(c(-1,16), c(-1,16), type = "n", xlab = "", ylab = "",
xaxs = "i", yaxs = "i",
main = sprintf("sign = %d, font = %d", sign, font))
grid(17, 17, lty = 1) ; mtext(paste("MBCS:", MB))
for(i in r) try(points(i%%16, i%/%16, pch = sign*i, font = font,...))
}
TestChars()
try(TestChars(sign = -1))
TestChars(font = 5) # Euro might be at 160 (0+10*16).
# macOS has apple at 240 (0+15*16).
try(TestChars(-1, font = 2)) # bold
In [4]:
library(yarrr)
# Here is a basic scatterplot with standard (non-transparent) colors:
# Plot with Standard Colors
plot(x = pirates$height,
y = pirates$weight,
col = "blue",
pch = 16,
main = "col ='blue'")
In [5]:
# Now here’s the same plot using the transparent() function in the yarrr package:
# Plot with transparent colors using the transparent() function in the yarrr package
plot(x = pirates$height,
y = pirates$weight,
col = yarrr::transparent("blue", trans.val = .9),
pch = 16,
main = "col = yarrr::transparent('blue', .9)")
# Later we’ll cover more advanced ways to come up with colors using color palettes (using the RColorBrewer package or the piratepal() function in the yarrr package) and functions that generate shades of colors based on numeric data (like the colorRamp2() function in the circlize package).
In [5]:
# Now here’s the same plot using the transparent() function in the yarrr package:
# Plot with transparent colors using the transparent() function in the yarrr package
plot(x = pirates$height,
y = pirates$weight,
col = yarrr::transparent("blue", trans.val = .9),
pch = 16,
main = "col = yarrr::transparent('blue', .9)")
# Later we’ll cover more advanced ways to come up with colors using color palettes (using the RColorBrewer package or the piratepal() function in the yarrr package) and functions that generate shades of colors based on numeric data (like the colorRamp2() function in the circlize package).
In [5]:
hist(x = ChickWeight$weight,
main = "Chicken Weights",
xlab = "Weight",
xlim = c(0, 500))
In [9]:
# We can get more fancy by adding additional arguments like breaks = 20 to force there to be 20 bins, and col = "papayawhip" and bg = "hotpink" to make it a bit more colorful:
hist(x = ChickWeight$weight,
main = "Fancy Chicken Weight Histogram",
xlab = "Weight",
ylab = "Frequency",
breaks = 20, # 20 Bins
xlim = c(0, 500),
col = "papayawhip", # Filling Color
border = "hotpink") # Border Color
In [7]:
# If you want to plot two histograms on the same plot, for example, to show the distributions of two different groups, you can use the argument to the second plot.
hist(x = ChickWeight$weight[ChickWeight$Diet == 1],
main = "Two Histograms in one",
xlab = "Weight",
ylab = "Frequency",
breaks = 20,
xlim = c(0, 500),
col = gray(0, .5))
hist(x = ChickWeight$weight[ChickWeight$Diet == 2],
breaks = 30,
add = TRUE, # Add plot to previous one!
col = gray(1, .8))
In [10]:
# A barplot typically shows summary statistics for different groups. The primary argument to a barplot is height: a vector of numeric values which will generate the height of each bar. To add names below the bars, use the names.arg argument. For additional arguments specific to barplot(), look at the help menu with ?barplot:
barplot(height = 1:5, # A vector of heights
names.arg = c("G1", "G2", "G3", "G4", "G5"), # A vector of names
main = "Example Barplot",
xlab = "Group",
ylab = "Height")
In [16]:
# Of course, you should plot more interesting data than just a vector of integers with a barplot. In the plot below, I create a barplot with the average weight of chickens for each week:
# Calculate mean weights for each time period
diet.weights <- aggregate(weight ~ Time,
data = ChickWeight,
FUN = mean)
# Create barplot
barplot(height = diet.weights$weight,
names.arg = diet.weights$Time,
xlab = "Week",
ylab = "Average Weight",
main = "Average Chicken Weights by Time",
col = "mistyrose")
In [17]:
# Clustered barplot
# I can represent these data in a matrix as follows. In order for the final barplot to include the condition names, I’ll add row and column names to the matrix with colnames() and rownames().
swim.data <- cbind(c(2.1, 3), # Naked Times
c(1.5, 3)) # Clothed Times
colnames(swim.data) <- c("Naked", "Clothed")
rownames(swim.data) <- c("No Shark", "Shark")
# Print result
swim.data
In [20]:
library(yarrr)
# Now, when I enter this matrix as the height = swim.data argument to barplot(), I’ll get multiple bars.
barplot(height = swim.data,
beside = TRUE, # Put the bars next to each other
legend.text = TRUE, # Add a legend
col = c(transparent("green", .2),
transparent("red", .2)),
main = "Swimming Speed Experiment",
ylab = "Speed (in meters / second)",
xlab = "Clothing Condition",
ylim = c(0, 4))
In [1]:
require(stats) # both 'density' and its default method
with(faithful, {
plot(density(eruptions, bw = 0.15))
rug(eruptions)
rug(jitter(eruptions, amount = 0.01), side = 3, col = "light blue")
})
In [2]:
round(jitter(c(rep(1, 3), rep(1.2, 4), rep(3, 3))), 3)
# These two 'fail' with S-plus 3.x:
jitter(rep(0, 7))
jitter(rep(10000, 5))
In [7]:
library(yarrr)
# Diagram of some examples
plot(1, ylim = c(0, 1), xlim = c(0, 12), bty = "n",
xaxt = "n", yaxt = "n", ylab = "", xlab = "", type = "na")
text(6, .9, "transparent('red', trans.val = x)")
points(x = 1:11, y = rep(.8, 11), pch = 16,
col = transparent("red", seq(0, 1, .1)), cex = 2)
text(x = 1:11, y = rep(.85, 11), seq(0, 1, .1))
text(6, .7, "transparent('red', trans.val = x)")
points(x = 1:11, y = rep(.6, 11), pch = 16,
col = transparent("blue", seq(0, 1, .1)), cex = 2)
text(x = 1:11, y = rep(.65, 11), seq(0, 1, .1))
text(6, .5, "transparent('forestgreen', trans.val = x)")
points(x = 1:11, y = rep(.4, 11), pch = 16,
col = transparent("forestgreen", seq(0, 1, .1)), cex = 2)
text(x = 1:11, y = rep(.45, 11), seq(0, 1, .1))
text(6, .3, "transparent('orchid1', trans.val = x)")
points(x = 1:11, y = rep(.2, 11), pch = 16,
col = transparent("orchid1", seq(0, 1, .1)), cex = 2)
text(x = 1:11, y = rep(.25, 11), seq(0, 1, .1))
In [8]:
# Scatterplot with transparent colors
a.x <- rnorm(100, mean = 0, sd = 1)
a.y <- a.x + rnorm(100, mean = 0, sd = 1)
par(mfrow = c(3, 3))
for(trans.val.i in seq(0, .1, length.out = 9)) {
plot(a.x, a.y, pch = 16, col = transparent("blue", trans.val.i), cex = 1.5,
xlim = c(-5, 5), ylim = c(-5, 5), xlab = "x", ylab = "y",
main = paste("trans.val = ", round(trans.val.i, 2), sep = ""))
}