如何为矩阵中的分类时间序列数据生成更好的图?
How to produce a nicer plot for my categorical time series data in a matrix?
我想在图形 window 的单独绘图上绘制此矩阵的每一行。
mat <-
structure(c("g", "b", "c", "e", "g", "b", "g", "g", "e", "e",
"a", "b", "b", "e", "c", "f", "d", "f", "g", "c", "f", "g", "b",
"e", "a", "b", "c", "a", "c", "g", "c", "d", "e", "d", "b", "f",
"e", "f", "a", "f", "c", "f", "e", "f", "d", "d", "f", "a", "d",
"f"), .Dim = c(5L, 10L))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] "g" "b" "a" "f" "f" "b" "c" "f" "c" "d"
#[2,] "b" "g" "b" "d" "g" "c" "d" "e" "f" "f"
#[3,] "c" "g" "b" "f" "b" "a" "e" "f" "e" "a"
#[4,] "e" "e" "e" "g" "e" "c" "d" "a" "f" "d"
#[5,] "g" "e" "c" "c" "a" "g" "b" "f" "d" "f"
根据我的回答,我需要先将这个矩阵转换为数值。
v <- as.character(mat)
lev <- sort(unique(v)) ## sorted unique labels
# [1] "a" "b" "c" "d" "e" "f" "g"
mat_int <- matrix(match(v, lev), nrow = nrow(mat))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] 7 2 1 6 6 2 3 6 3 4
#[2,] 2 7 2 4 7 3 4 5 6 6
#[3,] 3 7 2 6 2 1 5 6 5 1
#[4,] 5 5 5 7 5 3 4 1 6 4
#[5,] 7 5 3 3 1 7 2 6 4 6
现在我正在使用以下代码生成我的图表。
par(mfrow=c(5,1))
matplot(t(mat_int)[, c(1)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(2)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(3)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(4)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(5)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
但我有几个问题:
- 五个图中每个图的 y 轴上的标签仅包含部分结果(假设第二个图缺失 "a")。有没有一种方法可以列出所有五个图的 y 轴上的所有分类变量? (也就是说,每一个地块都有标签:a,b,c,d,e,f,g。
- 现在我必须在一个大页面上制作这个图,以便清楚地显示所有 y 轴标签。有没有什么办法可以将我的绘图更紧密地排列在一起以保存 space,以便它们可以放在较小的页面中?
谢谢。
我想指出3个问题。
这里使用plot
昨天在 R graphics: How to plot a sequence of characters (pure categorical time series) 中,您试图在单个图形上绘制 2 行或更多行的矩阵,所以我建议 matplot
。但是现在你只想分别绘制不同的行,因此正常的 plot
就足够了。
随着您的更新,您可以使用
plot(mat_int[2,], yaxt="n", type = "l", ylim = seq_along(lev), xlab = "time", ylab = "category")
设置一个普通的ylim
一旦您决定生成单独的图表,您需要设置一个通用的 ylim
,以便 y-axis 可以在不同的图表之间进行比较。放
ylim = c(1, length(lev))
每个 plot
里面。请注意,ylim
采用长度为 2 的向量,给出最小值和最大值,因此 ylim = 1:length(lev)
是错误的。
调整绘图页边距和/或在更大的页面上绘图
R 图有两个边距。一个是图形 window 的外边距,另一个是内边距。边距以两种单位测量:线和英寸。相关图形参数为:
oma: *o*uter *ma*rgin in lines
omi: *o*uter *m*argin in *i*nches
mar: inner *mar*gin in lines
mai: inner *ma*rgin in *i*nches
通常以行为单位更方便,因为 x-axis 标签、绘图标题等按行放置,因此使用 oma
和 mar
而不是 omi
和 mai
让我们更好地了解如何根据需要设置边距。所有参数都采用长度为 4 的向量,在 "bottom"、"left"、"top"、"right" 上留出余量,即从底部顺时针方向。
通常你不需要对外边距做任何事情,它们默认都是零。您可以通过 par(c("oma","omi"))
来查看。请注意,将打开一个新的图形 window,但您可以忽略它或根据需要将其关闭。不唤醒是无法查询图形参数的 window,见grab par values without opening a graphics device?.
我们想将"top"、"bottom"处的内边距设置为0,这样所有的地块就会垂直拼接在一起。通过这样做,我们必须在 "top" 和 "bottom" 处设置外边距,以便为轴和标题留出一些额外的 space(如果需要)。
new_par <- old_par <- par(c("mar", "oma"))
new_par$mar[1] <- 0; new_par$mar[3] <- 0 ## inner bottom and top margin to 0
new_par$oma[1] <- 3; new_par$oma[3] <- 3 ## outer bottom and top margin to 3
par(new_par) ## set new par
par(mfrow = c(5,1))
plot(mat_int[1, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(3, axTicks(3)) ## place an x-axis on the top
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA) ## draw ticks, but no labels
plot(mat_int[2, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[3, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[4, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[5, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
我想在图形 window 的单独绘图上绘制此矩阵的每一行。
mat <-
structure(c("g", "b", "c", "e", "g", "b", "g", "g", "e", "e",
"a", "b", "b", "e", "c", "f", "d", "f", "g", "c", "f", "g", "b",
"e", "a", "b", "c", "a", "c", "g", "c", "d", "e", "d", "b", "f",
"e", "f", "a", "f", "c", "f", "e", "f", "d", "d", "f", "a", "d",
"f"), .Dim = c(5L, 10L))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] "g" "b" "a" "f" "f" "b" "c" "f" "c" "d"
#[2,] "b" "g" "b" "d" "g" "c" "d" "e" "f" "f"
#[3,] "c" "g" "b" "f" "b" "a" "e" "f" "e" "a"
#[4,] "e" "e" "e" "g" "e" "c" "d" "a" "f" "d"
#[5,] "g" "e" "c" "c" "a" "g" "b" "f" "d" "f"
根据我
v <- as.character(mat)
lev <- sort(unique(v)) ## sorted unique labels
# [1] "a" "b" "c" "d" "e" "f" "g"
mat_int <- matrix(match(v, lev), nrow = nrow(mat))
# [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
#[1,] 7 2 1 6 6 2 3 6 3 4
#[2,] 2 7 2 4 7 3 4 5 6 6
#[3,] 3 7 2 6 2 1 5 6 5 1
#[4,] 5 5 5 7 5 3 4 1 6 4
#[5,] 7 5 3 3 1 7 2 6 4 6
现在我正在使用以下代码生成我的图表。
par(mfrow=c(5,1))
matplot(t(mat_int)[, c(1)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(2)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(3)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(4)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
matplot(t(mat_int)[, c(5)], yaxt = "n", type = "l", xlab = "time", ylab = "category")
axis(2, seq_along(lev), labels = lev)
但我有几个问题:
- 五个图中每个图的 y 轴上的标签仅包含部分结果(假设第二个图缺失 "a")。有没有一种方法可以列出所有五个图的 y 轴上的所有分类变量? (也就是说,每一个地块都有标签:a,b,c,d,e,f,g。
- 现在我必须在一个大页面上制作这个图,以便清楚地显示所有 y 轴标签。有没有什么办法可以将我的绘图更紧密地排列在一起以保存 space,以便它们可以放在较小的页面中?
谢谢。
我想指出3个问题。
这里使用plot
昨天在 R graphics: How to plot a sequence of characters (pure categorical time series) 中,您试图在单个图形上绘制 2 行或更多行的矩阵,所以我建议 matplot
。但是现在你只想分别绘制不同的行,因此正常的 plot
就足够了。
随着您的更新,您可以使用
plot(mat_int[2,], yaxt="n", type = "l", ylim = seq_along(lev), xlab = "time", ylab = "category")
设置一个普通的ylim
一旦您决定生成单独的图表,您需要设置一个通用的 ylim
,以便 y-axis 可以在不同的图表之间进行比较。放
ylim = c(1, length(lev))
每个 plot
里面。请注意,ylim
采用长度为 2 的向量,给出最小值和最大值,因此 ylim = 1:length(lev)
是错误的。
调整绘图页边距和/或在更大的页面上绘图
R 图有两个边距。一个是图形 window 的外边距,另一个是内边距。边距以两种单位测量:线和英寸。相关图形参数为:
oma: *o*uter *ma*rgin in lines
omi: *o*uter *m*argin in *i*nches
mar: inner *mar*gin in lines
mai: inner *ma*rgin in *i*nches
通常以行为单位更方便,因为 x-axis 标签、绘图标题等按行放置,因此使用 oma
和 mar
而不是 omi
和 mai
让我们更好地了解如何根据需要设置边距。所有参数都采用长度为 4 的向量,在 "bottom"、"left"、"top"、"right" 上留出余量,即从底部顺时针方向。
通常你不需要对外边距做任何事情,它们默认都是零。您可以通过 par(c("oma","omi"))
来查看。请注意,将打开一个新的图形 window,但您可以忽略它或根据需要将其关闭。不唤醒是无法查询图形参数的 window,见grab par values without opening a graphics device?.
我们想将"top"、"bottom"处的内边距设置为0,这样所有的地块就会垂直拼接在一起。通过这样做,我们必须在 "top" 和 "bottom" 处设置外边距,以便为轴和标题留出一些额外的 space(如果需要)。
new_par <- old_par <- par(c("mar", "oma"))
new_par$mar[1] <- 0; new_par$mar[3] <- 0 ## inner bottom and top margin to 0
new_par$oma[1] <- 3; new_par$oma[3] <- 3 ## outer bottom and top margin to 3
par(new_par) ## set new par
par(mfrow = c(5,1))
plot(mat_int[1, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(3, axTicks(3)) ## place an x-axis on the top
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA) ## draw ticks, but no labels
plot(mat_int[2, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[3, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[4, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
xaxt = "n", ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)
axis(1, axTicks(1), labels = NA)
plot(mat_int[5, ], yaxt = "n", type = "l", xlab = "time", ylab = "category",
ylim = c(1, length(lev)))
axis(2, seq_along(lev), labels = lev)