【问题标题】:Draw ggplots in the plot grid by column - plot_grid() function of the cowplot package在绘图网格中按列绘制 ggplots - cowplot 包的 plot_grid() 函数
【发布时间】:2020-11-14 09:10:36
【问题描述】:

我正在使用 cowplot 包的 plot_grid() 函数在网格中绘制 ggplots,想知道是否有办法按列而不是按行绘制图?

library(ggplot2)
library(cowplot)

df <- data.frame(
    x = c(3,1,5,5,1),
    y = c(2,4,6,4,2)
)

# Create plots: say two each of path plot and polygon plot 
p <- ggplot(df)
p1 <- p + geom_path(aes(x,y)) + ggtitle("Path 1")
p2 <- p + geom_polygon(aes(x,y)) + ggtitle("Polygon 1")
p3 <- p + geom_path(aes(y,x)) + ggtitle("Path 2")
p4 <- p + geom_polygon(aes(y,x)) + ggtitle("Polygon 2")

plots <- list(p1,p2,p3,p4)
plot_grid(plotlist=plots, ncol=2) # plots are drawn by row

我想在第一列中绘制 P1 和 P2,在第二列中绘制 p3 和 p4,如下所示:

plots <- list(p1, p3, p2, p4) # plot sequence changed
plot_grid(plotlist=plots, ncol=2)

实际上我可以有 4、6 或 8 个地块。绘图网格中的行数会有所不同,但总是有 2 列。在每种情况下,我都想按列(垂直)填充绘图网格,以便我的前 2、3 或 4 个绘图(视情况而定)彼此重叠。如果我可以指定类似 par(mfcol = c(n,2)) 的内容,我想避免对这些不同的排列进行硬编码。

【问题讨论】:

    标签: ggplot2


    【解决方案1】:

    正如您所观察到的,plot_grid() 按行绘制图。我不相信有任何方法可以改变它,所以如果你想保持使用plot_grid()(这可能是最方便的),那么一种方法可能是改变你的情节列表中项目的顺序以匹配plot_grid() 需要什么,知道列数。

    这是我编写的一个函数。基本思路是:

    • 为列表中的项目数创建一个索引列表(即1:length(your_list)),
    • 将索引号放入具有指定行数的矩阵中,
    • 将该矩阵读回到另一个索引向量中按列
    • 根据新排序的索引重新排序列表

    即使列表中的项目数不能被预期的列数整除(例如 3 列中排列的 8 个项目的列表),我也尝试构建一种方法来完成这项工作。

    reorder_by_col <- function(myData, col_num) {
      x <- 1:length(myData)   # create index vector
      length(x) <- prod(dim(matrix(x, ncol=col_num)))  # adds NAs as necessary
      temp_matrix <- matrix(x, ncol=col_num, byrow = FALSE)
      new_x <- unlist(split(temp_matrix, rep(1:ncol(temp_matrix), each=row(temp_matrix))))
      names(new_x) <- NULL # not sure if we need this, but it forces an unnamed vector
      return(myData[new_x])
    }
    

    这一切都是在 Google 的帮助下编写的,专门回答了 here 和 here 发布的问题。

    您现在无需重新排序即可看到差异:

    plots <- list(p1,p2,p3,p4)
    plot_grid(plotlist=plots, ncol=2)
    

    ...并使用新方法重新排序:

    newPlots <- reorder_by_col(myData=plots, col_num=2)
    plot_grid(plotlist=newPlots, ncol=2)
    

    【讨论】:

    • 感谢 chemdork123。我试过你的功能。它适用于四个地块,但不适用于六个或八个地块。需要明确的是,当我的 plotlist 有六个图时,我希望 plot_grid() 函数在第一列中绘制前三个,在第二列中绘制后三个。同样,对于 plotlist 中的八个图,plot_grid() 函数应在第一列中绘制前四个图,在第二列中绘制其余四个。
    • 当我的绘图列表包含六个绘图 {p1,p2,p3,p5,p6,p7} 时,函数中的变量 new_x 返回 {1,3,5,2,4,6}。但是,理想情况下,它应该为 plot_grid() 返回 {1,5,2,6,3,7} 以在第一列中绘制 P1 到 P3,在第二列中绘制 P5 到 P7。同样,对于 plotlist {p1,p2,p3,p4,p5,p6,p7,p8} 中的八个图,您的 new_x 返回 {1,3,5,7,2,4,6,8} 而不是所需的 {1 ,5,2,6,3,7,4,8}。
    • 所以我用 Reduce() 修改了函数如下:reorder_by_col &lt;- function(myData, col_num) { x &lt;- 1:length(myData) # create index vector temp_matrix &lt;- matrix(x, ncol=col_num, byrow = FALSE) new_x &lt;- Reduce(c,split(temp_matrix, 1:(length(myData)/col_num))) return(myData[new_x]) } 这给了我想要的输出,至少当想要的列数是 2 并且 plotlist 包含偶数地块。
    • 我希望 plot_grid() 提供一个附加参数 'byRow' (TRUE/FALSE) 以按行或按列绘制!
    • 完成,添加了一个新问题:github.com/wilkelab/cowplot/issues/161
    【解决方案2】:

    The argument, byrow, has now been added to plot_grid.

    如果您想拥有num_plots &lt; nrow * ncol,剩余位置将为空。

    您现在可以调用:

    library(ggplot2)
    
    df <- data.frame(
      x = 1:10, y1 = 1:10, y2 = (1:10)^2, y3 = (1:10)^3, y4 = (1:10)^4
    )
    
    p1 <- ggplot(df, aes(x, y1)) + geom_point()
    p2 <- ggplot(df, aes(x, y2)) + geom_point()
    p3 <- ggplot(df, aes(x, y3)) + geom_point()
    
    cowplot::plot_grid(p1, p2, p3, byrow = FALSE)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 2019-11-25
      • 2019-03-25
      • 1970-01-01
      • 2018-03-20
      • 1970-01-01
      相关资源
      最近更新 更多