计算R中给定量图的最佳网格布局尺寸

时间:2015-08-14 19:20:55

标签: r rows dimensions

我在ggplot中有12个图,我正在使用grid.arrange安排它们。我手动将网格中的行数设置为4,列数为3.由于3 x 4 = 12,这就像魅力一样。

但如果我有任意数量的情节怎么办?说13 ...我将如何以编程方式找到要使用的行数和列数,使整个绘图成为最“方形”的形状?

我想在R中这样做。

更新 链接到数据:http://github.com/ngfrey/DataGenii/blob/master/exampleMedicalData.csv

这是我今天早上工作的代码。希望它能提供一个更具说明性的例子。请注意我如何设置函数的return(list(plots=plots, numrow=4, numcol=3))部分中的行数和列数:

makePlots<- function(fdf){
idx<- which(sapply(fdf, is.numeric))
idx<- data.frame(idx)
names(idx)<- "idx"
idx$names<- rownames(idx)
plots<- list()

for(i in 2:length(idx$idx)) {
  varname<- idx$names[i]
  mydata<- fdf[, idx$names[i]]
  mydata<- data.frame(mydata)
  names(mydata)<- varname
  g<- ggplot(data=mydata, aes_string(x=varname) )
  g<- g + geom_histogram(aes(y=..density..), color="black", fill='skyblue')+ geom_density() + xlab(paste(varname))
  print(g)


  plots<- c(plots, list(g))
}

return(list(plots=plots, numrow=4, numcol=3 ))
}
res<- makePlots(fdf)
do.call(grid.arrange, c(res$plots, nrow=res$numrow, ncol=res$numcol))

3 个答案:

答案 0 :(得分:1)

?n2mfrow为您找到默认布局;事实上,如果grid.arrangenrow缺失,则ncol已使用它

grid.arrange(grobs = replicate(7, rectGrob(), simplify=FALSE))

enter image description here

答案 1 :(得分:0)

在实践中,可以合理地显示的图表数量有限且几乎没有美学上令人满意的安排,因此您可以将表格列表。

但是,我们可以做的是指定较大尺寸与较小尺寸之比的公差。然后我们找到最接近两个数字来计算我们的目标。如果这些都在容忍范围内,我们就完成了。否则,我们会向目标添加浪费。这终止于找到合适的一对或在下一个最大的正方形。 (容差应该> 1)。

最接近的两个数字中最小的一个因子n

fact<-function(n) {
  k<-floor(sqrt(n));
  for(i in k:1) {if (n%%i == 0) return(i)}
}

在容差范围内搜索近似平方

nearsq<-function(n,tol=5/3+0.001) {
  m<-ceiling(sqrt(n))^2;
  for(i in n:m) {
    a<-fact(i);
    b<-i/a;
    if(b/a < tol) return(c(a,b))
  }
}

实施例

#probably too many plots
nearsq(83)
#> [1]  8 11

#a more reasonable range of plots, tabulated
cbind(12:36,t(Vectorize(nearsq)(12:36)))
      [,1] [,2] [,3]
 [1,]   12    3    4
 [2,]   13    3    5
 [3,]   14    3    5
 [4,]   15    3    5
 [5,]   16    4    4
 [6,]   17    4    5
 [7,]   18    4    5
 [8,]   19    4    5
 [9,]   20    4    5
[10,]   21    4    6
[11,]   22    4    6
[12,]   23    4    6
[13,]   24    4    6
[14,]   25    5    5
[15,]   26    5    6
[16,]   27    5    6
[17,]   28    5    6
[18,]   29    5    6
[19,]   30    5    6
[20,]   31    5    7
[21,]   32    5    7
[22,]   33    5    7
[23,]   34    5    7
[24,]   35    5    7
[25,]   36    6    6

答案 2 :(得分:0)

在这里,我是如何让这个坏孩子上班的: (我仍然可以收紧轴标签,并且可能压缩makePlots()函数中的前两个if语句,以便它运行得更快,但我会在以后的日期/后期处理它

library(gmp)
library(ggplot2)
library(gridExtra)

############
factors <- function(n)
{
   if(length(n) > 1) 
   {
      lapply(as.list(n), factors)
   } else
   {
      one.to.n <- seq_len(n)
      one.to.n[(n %% one.to.n) == 0]
   }
}


###########
makePlots<- function(fdf){
idx<- which(sapply(fdf, is.numeric))
idx<- data.frame(idx)
names(idx)<- "idx"
idx$names<- rownames(idx)
plots<- list()

for(i in 2:length(idx$idx)) {
  varname<- idx$names[i]
  mydata<- fdf[, idx$names[i]]
  mydata<- data.frame(mydata)
  names(mydata)<- varname
  g<- ggplot(data=mydata, aes_string(x=varname) )
  g<- g + geom_histogram(aes(y=..density..), color="black", fill='skyblue')+ geom_density() + xlab(paste(varname))
  print(g)


  plots<- c(plots, list(g))
}

numplots<- 0
#Note: The reason I put in length(idx$idx)-1 is because the first column is the row indicies, which are usually numeric ;)
#isprime returns 0 for non-prime numbers, 2 for prime numbers
if(length(idx$idx) == 2){
  numplots<- length(idx$idx)
  ncolx<- 1
  nrowx<- 2
} else if(length(idx$idx)==3){
  numplots<- length(idx$idx)
  ncolx<- 1
  nrowx<- 3
} else if(isprime((length(idx$idx)-1)) !=0){ 
  numplots<- length(idx$idx)
  facts<- factors(numplots)
  ncolx<- facts[length(facts)/2]
  nrowx<- facts[(length(facts)/2) + 1]

} else{numplots<- (length(idx$idx)-1)
  facts<- factors(numplots)
  ncolx<- facts[length(facts)/2]
  nrowx<- facts[(length(facts)/2) + 1]}

if(abs(nrowx-ncolx)>2){
  ncolx<- ncolx+1
  nrowx<- ceiling(numplots/ncolx)
}


return(list(plots=plots, numrow=nrowx, numcol=ncolx ))
}
res<- makePlots(fdf)
do.call(grid.arrange, c(res$plots, nrow=res$numrow, ncol=res$numcol))