作者andrew43 (讨厌有好心推文後删文者)
看板R_Language
标题[分享] 柱状图的低阶绘图范例
时间Wed Dec 16 01:22:28 2015
因为常被问到,也好久没来「上班」了,发一个教学文。
问题:怎麽画出像下面这种图?也就是二因子的柱状图。
http://imgur.com/riRkMGA
比较麻烦的部份是:
1. 同时有线条填色与颜色填色
2. 放在外部的图示
3. 有 error bar
以下请见该图的原始码。
# 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()
[关键字]: 柱状图 线条填色 外部图示
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 125.230.76.169
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/R_Language/M.1450200152.A.E08.html
※ 编辑: andrew43 (125.230.76.169), 12/16/2015 01:25:06
※ 编辑: andrew43 (125.230.76.169), 12/16/2015 01:29:21
1F:推 celestialgod: 推 12/16 02:21
2F:推 ayugioh2003: 推 12/18 23:22
3F:推 cywhale: push~~ practical issue~~ 12/19 23:42
4F:推 abcggg: 推 感谢分享! 02/16 08:35