生成具有交替轴和不同比例的堆叠 multi-panel 图
Produce stacked multi-panel plot with alternating axes and different scales
假设我们有这个数据:
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"), value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
我想为每个 variable
绘制一个图 value
vs value
,这样我就有 6 个面板,格式如下,其中字母代表轴的位置, p
显示面板所在的位置。
a2 p
a3 p p
a4 p p p
a1 a2 a3
我知道如果数据很长我可以绘制每一个并安排...,例如
par(.....)
plot(a1 ~ a2, data=longdat)
plot(a1 ~ a3, data=longdat)
plot(a1 ~ a4, data=longdat)
......
如果我能做到这一点,也许有一个快速的方法吗?
最好我想知道是否已经有办法做到这一点,比如 ggplot2
中的 facet_wrap
或 facet_grid
Lattice
似乎有我想要的形状图(见下文),但我只能看到如何为 using two axes split per factor 执行此操作。这里的直方图不是必需的这只是一个例子..
lattice 可以做类似的事情,但不是我想要的..
xyplot(value~value|variable,
data = a,
scales=list(alternating=FALSE,relation="same"),
layout=c(2,2))
通过重新排序数据,我也许可以完成这项工作,但是当您将 relation
更改为 "free"
时,您会在轴上为每个变量获得不同的比例,然后它将面板分解为单独的面板.
希望这就是您想要的。
x 是针对每个 z 的 x 绘制的。 “|”后面的变量是条件变量。这用于实现类似于 facet_grid() 的结果。布局通常根据您的地块大小或地块 window 按 lattice 选择。您可以强制采用如下所示的 2x2 布局,这似乎会自动将空的 space 放在右上角。
library("lattice")
dat <- data.frame(x=rnorm(15),z=rep(letters[1:3],each=5))
xyplot(x~x|z, data = dat, scales=list(alternating=FALSE), layout=c(2,2))
根据我对你问题的阅读,你想要的只是一个显示每对变量的散点图的图。通过使用 reshape2
包中的 dcast()
快速将数据从长格式转换为宽格式,使用基础图形中的 pairs()
可以轻松完成此操作。如下:
library(reshape2)
# assign some id variables to assist the conversion and cast
dat$id <- sequence(rle(as.character(dat$variable))$lengths)
dat2 <- dcast(dat, id ~ variable, value.var='value')
# plot
pairs(dat2[2:5], upper.panel=NULL)
这给我们留下了我认为你想要的情节。
从那里开始,如果您确实想在对角线或上图中添加 R 平方值、直方图等,您需要的代码可以在这里找到:
How to modify this Correlation Matrix plot?
例如:
panel.hist <- function(x, ...)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks; nB <- length(breaks)
y <- h$counts; y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col="cyan", ...)
}
pairs(dat2[2:5], upper.panel=NULL, diag.panel=panel.hist)
希望对您有所帮助。
编辑:使用 GGally (v1.0.1)
使用 GGally
包中的 ggpairs()
函数更容易。让 ggpairs()
绘制和定位散点图,然后从结果图中删除不需要的元素。首先,将数据转换为宽格式。
# Packages
library(GGally)
library(ggplot2)
library(tidyr)
# Data
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"),
value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
# Get the data in its wide format
dat$id <- sequence(rle(as.character(dat$variable))$lengths)
dat2 = spread(data = dat, key = variable, value = value)
# Base plot
gg = ggpairs(dat2,
columns = 2:5,
lower = list(continuous = "points"),
diag = list(continuous = "blankDiag"),
upper = list(continuous = "blank"))
使用从 到 trim 的代码关闭未指定的元素
# Trim off the diagonal spaces
n <- gg$nrow
gg$nrow <- gg$ncol <- n-1
v <- 1:n^2
gg$plots <- gg$plots[v > n & v%%n != 0]
# Trim off the last x axis label
# and the first y axis label
gg$xAxisLabels <- gg$xAxisLabels[-n]
gg$yAxisLabels <- gg$yAxisLabels[-1]
# Draw the plot
gg = gg +
theme_bw() +
theme(panel.grid = element_blank())
gg
原创
pairs()
函数让您接近,但如果您只想要布局矩阵中显示的六个面板,那么您可能必须手动构建它。您可以使用 grid
或 ggplot
和 gtable
构建图表。这是 ggplot / gtable
版本。
该脚本适用于您的 dat
数据文件(即长格式)。它构建了六个 ggplot
散点图的列表。 ggplots 被转换为 grobs,并提取相关轴——那些将成为新图表中的左轴和底轴的轴。构建 gtable 布局,并将散点图 grobs(仅限绘图面板)添加到布局中。修改布局以获取轴,然后再次修改布局以获取变量标签。最后,有一点整理。
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"),
value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
# Load packages
library("ggplot2")
library("plyr")
library("gtable")
library(grid)
# Number of items and item labels
item = unique(dat$variable)
n = length(item)
## List of scatterplots
scatter <- list()
for (i in 1:(n-1)) {
for (j in (i+1):n) {
# Data frame
df.point <- na.omit(data.frame(cbind(x = dat[dat$variable == item[i], 2], y = dat[dat$variable == item[j], 2])))
# Plot
p <- ggplot(df.point, aes(x, y)) +
geom_point(size = 1) +
theme_bw() +
theme(panel.grid = element_blank(),
axis.text = element_text(size = 6))
name <- paste0("Item", i, j)
scatter[[name]] <- p
} }
# Convert ggplots to grobs
scatterGrob <- llply(scatter, ggplotGrob)
# Extract the axes as grobs
# x axis
xaxes = subset(scatterGrob, grepl(paste0("^Item.", n), names(scatterGrob)))
xaxes = llply(xaxes, gtable_filter, "axis-b")
# y axis
yaxes = subset(scatterGrob, grepl("^Item1.*", names(scatterGrob)))
yaxes = llply(yaxes, gtable_filter, "axis-l")
# Tick marks and tick mark labels are easier to position if they are separated.
labelsb = list(); ticksb = list(); labelsl = list(); ticksl = list()
for(i in 1:(n-1)) {
x = xaxes[[i]][[1]][[1]]$children[[2]]
labelsb[[i]] = x$grobs[[2]]
ticksb[[i]] = x$grobs[[1]]
y = yaxes[[i]][[1]][[1]]$children[[2]]
labelsl[[i]] = y$grobs[[1]]
ticksl[[i]] = y$grobs[[2]]
}
## Extract the plot panels
scatterGrob <- llply(scatterGrob, gtable_filter, "panel")
## Set up initial gtable layout
gt <- gtable(unit(rep(1, n-1), "null"), unit(rep(1, n-1), "null"))
# Add scatterplots in the lower half of the matrix
k <- 1
for (i in 1:(n-1)) {
for (j in i:(n-1)) {
gt <- gtable_add_grob(gt, scatterGrob[[k]], t=j, l=i)
k <- k+1
} }
# Add rows and columns for axes
gt <- gtable_add_cols(gt, unit(0.25, "lines"), 0)
gt <- gtable_add_cols(gt, unit(1, "lines"), 0)
gt <- gtable_add_rows(gt, unit(0.25, "lines"), 2*(n-1))
gt <- gtable_add_rows(gt, unit(0.5, "lines"), 2*(n-1))
for (i in 1:(n-1)) {
gt <- gtable_add_grob(gt, ticksb[[i]], t=(n-1)+1, l=i+2)
gt <- gtable_add_grob(gt, labelsb[[i]], t=(n-1)+2, l=i+2)
gt <- gtable_add_grob(gt, ticksl[[i]], t=i, l=2)
gt <- gtable_add_grob(gt, labelsl[[i]], t=i, l=1)
}
# Add rows and columns for variable names
gt <- gtable_add_cols(gt, unit(1, "lines"), 0)
gt <- gtable_add_rows(gt, unit(1, "lines"), n+1)
for(i in 1:(n-1)) gt <- gtable_add_grob(gt,
textGrob(item[i], gp = gpar(fontsize = 8)), t=n+2, l=i+3)
for(i in 2:n) gt <- gtable_add_grob(gt,
textGrob(item[i], rot = 90, gp = gpar(fontsize = 8)), t=i-1, l=1)
# Add small gaps between the panels
for(i in (n-1):2) {
gt <- gtable_add_cols(gt, unit(0.4, "lines"), i+2)
gt <- gtable_add_rows(gt, unit(0.4, "lines"), i-1)
}
# Add margins to the whole plot
for(i in c(2*(n-1)+2, 0)) {
gt <- gtable_add_cols(gt, unit(.75, "lines"), i)
gt <- gtable_add_rows(gt, unit(.75, "lines"), i)
}
# Turn clipping off
gt$layout$clip = "off"
# Draw it
grid.newpage()
grid.draw(gt)
假设我们有这个数据:
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"), value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
我想为每个 variable
绘制一个图 value
vs value
,这样我就有 6 个面板,格式如下,其中字母代表轴的位置, p
显示面板所在的位置。
a2 p
a3 p p
a4 p p p
a1 a2 a3
我知道如果数据很长我可以绘制每一个并安排...,例如
par(.....)
plot(a1 ~ a2, data=longdat)
plot(a1 ~ a3, data=longdat)
plot(a1 ~ a4, data=longdat)
......
如果我能做到这一点,也许有一个快速的方法吗?
最好我想知道是否已经有办法做到这一点,比如 ggplot2
facet_wrap
或 facet_grid
Lattice
似乎有我想要的形状图(见下文),但我只能看到如何为 using two axes split per factor 执行此操作。这里的直方图不是必需的这只是一个例子..
lattice 可以做类似的事情,但不是我想要的..
xyplot(value~value|variable,
data = a,
scales=list(alternating=FALSE,relation="same"),
layout=c(2,2))
通过重新排序数据,我也许可以完成这项工作,但是当您将 relation
更改为 "free"
时,您会在轴上为每个变量获得不同的比例,然后它将面板分解为单独的面板.
希望这就是您想要的。
x 是针对每个 z 的 x 绘制的。 “|”后面的变量是条件变量。这用于实现类似于 facet_grid() 的结果。布局通常根据您的地块大小或地块 window 按 lattice 选择。您可以强制采用如下所示的 2x2 布局,这似乎会自动将空的 space 放在右上角。
library("lattice")
dat <- data.frame(x=rnorm(15),z=rep(letters[1:3],each=5))
xyplot(x~x|z, data = dat, scales=list(alternating=FALSE), layout=c(2,2))
根据我对你问题的阅读,你想要的只是一个显示每对变量的散点图的图。通过使用 reshape2
包中的 dcast()
快速将数据从长格式转换为宽格式,使用基础图形中的 pairs()
可以轻松完成此操作。如下:
library(reshape2)
# assign some id variables to assist the conversion and cast
dat$id <- sequence(rle(as.character(dat$variable))$lengths)
dat2 <- dcast(dat, id ~ variable, value.var='value')
# plot
pairs(dat2[2:5], upper.panel=NULL)
这给我们留下了我认为你想要的情节。
从那里开始,如果您确实想在对角线或上图中添加 R 平方值、直方图等,您需要的代码可以在这里找到: How to modify this Correlation Matrix plot?
例如:
panel.hist <- function(x, ...)
{
usr <- par("usr"); on.exit(par(usr))
par(usr = c(usr[1:2], 0, 1.5) )
h <- hist(x, plot = FALSE)
breaks <- h$breaks; nB <- length(breaks)
y <- h$counts; y <- y/max(y)
rect(breaks[-nB], 0, breaks[-1], y, col="cyan", ...)
}
pairs(dat2[2:5], upper.panel=NULL, diag.panel=panel.hist)
希望对您有所帮助。
编辑:使用 GGally (v1.0.1)
使用 GGally
包中的 ggpairs()
函数更容易。让 ggpairs()
绘制和定位散点图,然后从结果图中删除不需要的元素。首先,将数据转换为宽格式。
# Packages
library(GGally)
library(ggplot2)
library(tidyr)
# Data
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"),
value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
# Get the data in its wide format
dat$id <- sequence(rle(as.character(dat$variable))$lengths)
dat2 = spread(data = dat, key = variable, value = value)
# Base plot
gg = ggpairs(dat2,
columns = 2:5,
lower = list(continuous = "points"),
diag = list(continuous = "blankDiag"),
upper = list(continuous = "blank"))
使用从
# Trim off the diagonal spaces
n <- gg$nrow
gg$nrow <- gg$ncol <- n-1
v <- 1:n^2
gg$plots <- gg$plots[v > n & v%%n != 0]
# Trim off the last x axis label
# and the first y axis label
gg$xAxisLabels <- gg$xAxisLabels[-n]
gg$yAxisLabels <- gg$yAxisLabels[-1]
# Draw the plot
gg = gg +
theme_bw() +
theme(panel.grid = element_blank())
gg
原创
pairs()
函数让您接近,但如果您只想要布局矩阵中显示的六个面板,那么您可能必须手动构建它。您可以使用 grid
或 ggplot
和 gtable
构建图表。这是 ggplot / gtable
版本。
该脚本适用于您的 dat
数据文件(即长格式)。它构建了六个 ggplot
散点图的列表。 ggplots 被转换为 grobs,并提取相关轴——那些将成为新图表中的左轴和底轴的轴。构建 gtable 布局,并将散点图 grobs(仅限绘图面板)添加到布局中。修改布局以获取轴,然后再次修改布局以获取变量标签。最后,有一点整理。
dat <- structure(list(variable = c("a1", "a1", "a1", "a1", "a1", "a1",
"a2", "a2", "a2", "a2", "a2", "a2", "a3", "a3", "a3", "a3", "a3",
"a3", "a4", "a4", "a4", "a4", "a4", "a4"),
value = c(9.17804065427195,
-0.477515191225569, 0.189943035684685, -6.06095979017212, -10.4173631972868,
-6.119330192816, -14.3820530117637, 13.9823789620469, 15.6437973890843,
0.754856919261315, -0.887052526388938, 7.4096244573169, 0.61043977214679,
28.4639357142541, 15.4511442682744, 15.8118136384483, 6.65940292893,
0.467862281678766, 482.791905769932, 493.606761379037, 491.254828253119,
504.323684433231, 499.323576709646, 492.625278087471)), .Names = c("variable",
"value"), row.names = c(NA, -24L), class = "data.frame")
# Load packages
library("ggplot2")
library("plyr")
library("gtable")
library(grid)
# Number of items and item labels
item = unique(dat$variable)
n = length(item)
## List of scatterplots
scatter <- list()
for (i in 1:(n-1)) {
for (j in (i+1):n) {
# Data frame
df.point <- na.omit(data.frame(cbind(x = dat[dat$variable == item[i], 2], y = dat[dat$variable == item[j], 2])))
# Plot
p <- ggplot(df.point, aes(x, y)) +
geom_point(size = 1) +
theme_bw() +
theme(panel.grid = element_blank(),
axis.text = element_text(size = 6))
name <- paste0("Item", i, j)
scatter[[name]] <- p
} }
# Convert ggplots to grobs
scatterGrob <- llply(scatter, ggplotGrob)
# Extract the axes as grobs
# x axis
xaxes = subset(scatterGrob, grepl(paste0("^Item.", n), names(scatterGrob)))
xaxes = llply(xaxes, gtable_filter, "axis-b")
# y axis
yaxes = subset(scatterGrob, grepl("^Item1.*", names(scatterGrob)))
yaxes = llply(yaxes, gtable_filter, "axis-l")
# Tick marks and tick mark labels are easier to position if they are separated.
labelsb = list(); ticksb = list(); labelsl = list(); ticksl = list()
for(i in 1:(n-1)) {
x = xaxes[[i]][[1]][[1]]$children[[2]]
labelsb[[i]] = x$grobs[[2]]
ticksb[[i]] = x$grobs[[1]]
y = yaxes[[i]][[1]][[1]]$children[[2]]
labelsl[[i]] = y$grobs[[1]]
ticksl[[i]] = y$grobs[[2]]
}
## Extract the plot panels
scatterGrob <- llply(scatterGrob, gtable_filter, "panel")
## Set up initial gtable layout
gt <- gtable(unit(rep(1, n-1), "null"), unit(rep(1, n-1), "null"))
# Add scatterplots in the lower half of the matrix
k <- 1
for (i in 1:(n-1)) {
for (j in i:(n-1)) {
gt <- gtable_add_grob(gt, scatterGrob[[k]], t=j, l=i)
k <- k+1
} }
# Add rows and columns for axes
gt <- gtable_add_cols(gt, unit(0.25, "lines"), 0)
gt <- gtable_add_cols(gt, unit(1, "lines"), 0)
gt <- gtable_add_rows(gt, unit(0.25, "lines"), 2*(n-1))
gt <- gtable_add_rows(gt, unit(0.5, "lines"), 2*(n-1))
for (i in 1:(n-1)) {
gt <- gtable_add_grob(gt, ticksb[[i]], t=(n-1)+1, l=i+2)
gt <- gtable_add_grob(gt, labelsb[[i]], t=(n-1)+2, l=i+2)
gt <- gtable_add_grob(gt, ticksl[[i]], t=i, l=2)
gt <- gtable_add_grob(gt, labelsl[[i]], t=i, l=1)
}
# Add rows and columns for variable names
gt <- gtable_add_cols(gt, unit(1, "lines"), 0)
gt <- gtable_add_rows(gt, unit(1, "lines"), n+1)
for(i in 1:(n-1)) gt <- gtable_add_grob(gt,
textGrob(item[i], gp = gpar(fontsize = 8)), t=n+2, l=i+3)
for(i in 2:n) gt <- gtable_add_grob(gt,
textGrob(item[i], rot = 90, gp = gpar(fontsize = 8)), t=i-1, l=1)
# Add small gaps between the panels
for(i in (n-1):2) {
gt <- gtable_add_cols(gt, unit(0.4, "lines"), i+2)
gt <- gtable_add_rows(gt, unit(0.4, "lines"), i-1)
}
# Add margins to the whole plot
for(i in c(2*(n-1)+2, 0)) {
gt <- gtable_add_cols(gt, unit(.75, "lines"), i)
gt <- gtable_add_rows(gt, unit(.75, "lines"), i)
}
# Turn clipping off
gt$layout$clip = "off"
# Draw it
grid.newpage()
grid.draw(gt)