2015-08-14 34 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