我在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))
答案 0 :(得分:1)
?n2mfrow
为您找到默认布局;事实上,如果grid.arrange
和nrow
缺失,则ncol
已使用它
grid.arrange(grobs = replicate(7, rectGrob(), simplify=FALSE))
答案 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))