|
# dat 為輸入的二因子資料 |
|
set.seed(1234) |
|
dat <- data.frame( |
|
y = rnorm(80, 5, 2), |
|
x1 = gl(2, 40, labels = c("A","B")), |
|
x2 = gl(4, 10, labels = c("1","2","3","4")) |
|
) |
|
|
|
# 利用 tapply 求出各組之 mean 和 sd |
|
y.mean <- with(dat, tapply(y, paste(x1, x2, sep="."), mean)) |
|
y.sd <- with(dat, tapply(y, paste(x1, x2, sep="."), sd)) |
|
|
|
# 為了方便之後畫圖,把 y.mean 和 y.sd 轉成矩陣 |
|
# 矩陣各列表示 X2,各欄表示 X1 |
|
Y <- matrix(y.mean, 4) |
|
E <- matrix(y.sd, 4) |
|
colnames(Y) <- colnames(E) <- c("A", "B") |
|
rownames(Y) <- rownames(E) <- c("1", "2", "3", "4") |
|
|
|
# 接下來就開始畫圖 |
|
# 過程小小複雜,若有不了解可以逐步進行並觀看圖怎麼變化 |
|
|
|
# 先開一個畫布 |
|
# 因為我想把圖示畫在右側外部,所以 mar 和 xpd 要自行設定 |
|
dev.new(width = 5, height = 5) |
|
par(mar=c(4, 4, 1, 10) + 0.1, xpd = T) |
|
|
|
# 接下來是畫上柱狀圖主體 |
|
# 因為 X2 == "4" 柱體要畫成同時有「斜線填色」和「顏色填色」 |
|
# 所以 barplot 要畫二次 |
|
# 以下是第一次,只畫主要文字、框線和顏色填色 |
|
# 我習慣先自行算好 ylim |
|
# 注意 barplot 的回傳值被我定義為變數 bp(之後有用) |
|
bp <- barplot( |
|
Y, beside = T, |
|
xaxt = "n", ylim = c(0,10), |
|
ylab = "Title for y-axis (dat$y)", xlab = "Title for x-axis (dat$x1)", |
|
col = c(0,3,0,"yellow") |
|
) |
|
|
|
# 接下來是疊上 X2 == "4" 柱體的「斜線填色」 |
|
# 上一步已經畫過的就不要再畫一次 |
|
# 只要畫上 X2 == "4" 柱體的「斜線填色」即可 |
|
# 注意到 add = T 就是疊圖的作用 |
|
barplot( |
|
Y, beside = T, |
|
xaxt = "n", ylim = c(0,10), yaxt = "n", |
|
ylab = "", xlab = "", |
|
col = c(0,1,1,1), density = c(0,0,25,15), angle = c(NULL,NULL,45,135), |
|
border = c(0,0,0,0), |
|
add = T |
|
) |
|
|
|
# 這裡只是示範怎麼用 axis() |
|
axis(1, colMeans(bp), c("A", "B"), tick = F) |
|
|
|
# 這裡是畫「只向上方延伸的 error bar」 |
|
# 這時候 bp 的值(也就是每個柱的橫軸位置)就很有用了 |
|
arrows(bp, Y, bp, Y+E, length = 0.1, angle = 90) |
|
# 當然也可以再補畫上「向下方延伸的 error bar」 |
|
# 但這個例子不太適當就不做了 |
|
# 有需要的話請再加入 |
|
# arrows(bp, Y, bp, Y-E, length = 0.1, angle = 90) |
|
|
|
# 接下來是畫圖示 |
|
# 這裡示範如何把圖示畫在右側外部 |
|
# 需要與前面 par() 配合才行 |
|
# 也因為 X2 == "4" 柱體的同時有「斜線填色」和「顏色填色」 |
|
# 所以 legend() 一樣要畫兩次 |
|
# 第一次負責文字、線框、顏色填色 |
|
legend( |
|
"right", |
|
legend = c("1", "2", "3", "4"), |
|
fill = c(0,3,0,"yellow"), |
|
title = "Row name (dat$x2)", |
|
text.width = 5.5, |
|
box.lwd = 1, col = c(1,1,1,1), |
|
inset=c(-0.9,0) |
|
) |
|
|
|
# 第二次負責 X2 == "4" 的斜線填色就好 |
|
# 重覆的東西都不要再畫 |
|
# 注意兩次畫 legend 要完全重疊才會成功 |
|
# 因此我定了 text.width 之類看似多餘的參數 |
|
legend( |
|
"right", |
|
legend = c("", "", "", ""), |
|
fill = c(0,0,1,1), |
|
border = c(0,0,0,0), |
|
density = c(0,0,25,15), angle = c(NULL,NULL,45,135), |
|
title = "", |
|
text.width = 5.5, |
|
box.lwd = 0, col = c(0,0,0,0), |
|
inset=c(-0.9,0) |
|
) |
|
|
|
# 畫個框框 |
|
box() |