生成具有交替轴和不同比例的堆叠多面板图

时间:2015-03-09 13:46:59

标签: r plot ggplot2 lattice

想象一下,我们有这些数据:

    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")

我想为每个value制作一个情节value vs variable,这样我就有以下格式的6个面板,其中字母代表轴的位置和a 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)
......

如果我能做到这一切,那么有一个快速的方法吗? 我希望知道是否有办法实现这一点,例如facet_wrap中的facet_gridggplot2

Lattice似乎有我想要的形状(见下文)但我只能看到如何为using two axes split per factor执行此操作。这里的直方图不是必需的,这只是一个例子..

enter image description here

格子可以做类似的事情而不是我想做的事情。

xyplot(value~value|variable, 
       data = a, 
       scales=list(alternating=FALSE,relation="same"), 
       layout=c(2,2))

通过重新排序数据,我可以做到这一点,但是当你将relation更改为"free"时,每个变量的轴都会有不同的比例,然后将面板分成单独的面板。 / p>

3 个答案:

答案 0 :(得分:3)

编辑:使用GGally(v1.0.1)

使用ggpairs()包中的GGally函数更容易。让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"))

使用here中的代码修剪未使用的元素

# 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

enter image description here

<强>原始

pairs()函数会让您关闭,但如果您只需要布局矩阵中显示的六个面板,那么您可能需要手动构建它。您可以使用gridggplotgtable构建图表。这是ggplot / gtable版本。

该脚本适用于您的dat数据文件(即长格式)。它构造了六个ggplot散点图的列表。 ggplots被转换为grobs,并提取相关的轴 - 那些将成为新图表中左轴和下轴的轴。构建gtable布局,并将散点图凹槽(仅限绘图面板)添加到布局中。修改布局以获取轴,然后再次修改布局以采用变量标签。最后,还有一点整理。

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)

enter image description here

答案 1 :(得分:2)

从我对你的问题的阅读中,你想要的只是一个图表,显示每对变量的散点图。通过使用dcast()包中的reshape2快速将数据从长格式转换为宽格式,可以使用基本图形中的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)

这让我们看到了我认为你正在追求的阴谋。

enter image description here

从那里,如果你想在对角线或上图中添加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)

enter image description here

我希望有所帮助。

答案 2 :(得分:0)

我希望这就是你想要的。

对于每个z,对x绘制

。 &#34; |&#34;后面的变量是条件变量。这用于实现与facet_grid()类似的结果。通常根据您的绘图大小或绘图窗口通过晶格选择布局。您可以强制执行如下所示的2x2布局,这似乎会自动将空白区域置于右上角。

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))