2015-08-14 101 views
0

我在ggplot中有12个图,并且我正在使用grid.arrange进行排列。我手动设置网格中的行数为4,列数为3.由于3 x 4 = 12,这就像一个魅力。计算R中给定数量的图的最佳网格布局尺寸

但是如果我有任意数量的地块呢?说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)) 
+0

情节生成和你事先不知道他们有多少呢? – SabDeM

+1

你必须更具体地说明你的意思是方形的,否则'ceiling(sqrt(13))'? –

+0

我每天都会得到多个数据集,每个数据集都有数量未知的数值变量。我想为各个数据集中的每个数值变量创建一个密度图的网格。我会在一分钟内添加一个例子。 – nate

回答

0

这里之H我得到这个坏男孩的工作: (我仍然可以收紧轴标签,并可能压缩makePlots()函数中的前2个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)) 
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 
+0

谢谢!我还找到了解决这个问题的另一种方法。我也会发布我自己的答案! – nate

1

?n2mfrow找到您的默认布局;事实上,它已经使用grid.arrange如果nrowncol缺少

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

enter image description here