【问题标题】:Adjusting figure margins using split.screen使用 split.screen 调整图形边距
【发布时间】:2017-09-16 03:12:38
【问题描述】:

我正在尝试使用split.screen 选项生成多个图,并且我需要在页面上显示 7 个图。其中一个应单独绘制,另外 6 个应使用 for 循环重复绘制。

这是我正在执行的一些模拟的代码。它运行良好,但我有两个潜在的问题:

  1. 我不确定实际绘制了哪些图,因为我无法让分配的标签显示在更大的图上。
  2. 屏幕 1 上显示的图不是实际数据,因为我已经单独绘制了它并且知道它应该是什么样子。

模拟数据:

numpop = 2
N = 1250
nSNP = 5000
Fst = 0.001
omega = c(0.5, 0.5) 
propnExtreme = 0.1
nsim = 10
Fst.obs = vector(length = nSNP)
pdiffs = vector(length = nSNP)
genomat = matrix(nrow = N, ncol = nSNP)

for (i in 1:nSNP){
  p = runif(1, 0.1, 0.9)
  alpha = p * (1 - Fst) / Fst
  beta = (1 - p) * (1 - Fst) / Fst
  ps = rbeta(numpop, shape1 = alpha, shape2 = beta)
  vars = var(ps)
  pdiffs[i] = max(ps) - min(ps)
  Fst.obs[i] = vars / (p * (1 - p))

  for (j in 1:numpop){
    ind1 = (j-1) * N * omega[j] + 1
    ind2 = j * N * omega[j]
    freqs = c(ps[j]^2, 2 * ps[j] * (1 - ps[j]), (1 - ps[j])^2)
    genomat[ind1:ind2, i] = sample(c(0, 1, 2), size = N*omega[j], replace = TRUE, prob = freqs)

  }

}
snpmeans = colMeans(genomat)
pi = (1 + colSums(genomat)) / (2 + 2*nrow(genomat))
stdmat = scale(genomat, center=snpmeans, scale=sqrt(pi*(1-pi)))
pr = prcomp(stdmat, center=F, scale=F)

绘图:

get( getOption("device" ) )()
png(file="myplot.png", width=2000, height = 1200)
par(oma = c(0,0,3,0))

split.screen(c(1,2))       # split display into two screens
plot(pr$x, 
     col = c(rep("red", N*omega[1]), rep("blue", N*omega[2])), 
     main = "Whole genotype data")

split.screen(c(2, 3), screen = 2) # now split the second into 2x3
for(i in 1:8) ## 8=#of screens
{
  screen(i) # prepare screen i for output
  fA=0.5
  fa = 1-fA

  combined_SNP <- sample(c(0:2), N, prob=c(fA^2, 2*fA*fa, fa^2), replace=T)
  pheno_indep <-c()

  ##Phenotypes
  for (i in 1:length(combined_SNP)){
    if (combined_SNP[i] == '0') {
      pheno_indep<- c(pheno_indep, rnorm(1, mean = 0.07, sd = 1))
    } else if (combined_SNP[i ]== '1') {
      pheno_indep <- c(pheno_indep, rnorm(1, mean = 0, sd = 1))
    } else { 
      pheno_indep <- c(pheno_indep, rnorm(1, mean = -0.07, sd = 1))
    }
  } 

  l <- 1:N
  combined_indep <- cbind(combined_SNP, pheno_indep, l)
  sorted_combined <- combined_indep[order(combined_indep[, 2]), ]

  ##eps data
  f = 0.1
  Nums = nrow(sorted_combined)
  keep <- c(1:(f*Nums), (Nums-(f*Nums)+1):Nums)
  epsdat<- c(rep("0", f*Nums), rep("1", f*Nums))
  EPS_dat <- as.factor(cbind(sorted_combined[keep, ], epsdat))
  dim(EPS_dat) <- c(length(keep), 4)
  #colnames(EPS_dat) <- c("Genotypes", "Phenotypes", "ID", "position")
  PC_EPS <- prcomp((genomat[EPS_dat[, 3], ]))
  plot(PC_EPS$x, 
       col=c(rep("red", f*Nums), rep("blue", f*Nums)))

}
close.screen(all=TRUE)
dev.off()

结果:

我已经花了很多时间试图解决这个问题,即使是像 layout.show 这样的其他软件包也是如此。谢谢!

【问题讨论】:

    标签: r plot


    【解决方案1】:

    以下是您期望绘制的内容吗? (我在小图中添加了屏幕标题以进行说明)

    当您拆分屏幕时,您应该在控制台上看到以下内容:

    > split.screen(c(1, 2))
    [1] 1 2
    
    # (code used to plot first chart on the left)
    
    > split.screen(c(2, 3), screen = 2)
    [1] 3 4 5 6 7 8
    

    如帮助文件?split.screen 中所述,这是新创建屏​​幕的屏幕编号向量。因此,您的有效屏幕编号为 1(已绘制)和 3-8(6 个小屏幕)。

    因此,下一行无法按预期工作,因为您现在循环的是屏幕 1-8 而不是屏幕 3-8。

    # instead of
    for(i in 1:8) ## 8=#of screens
    
    # use this
    for(i in 3:8) ## 8=#of screens
    

    附带说明,您还应该为嵌套循环使用不同的循环计数器。您的外部循环(对于 6 个小图)使用 i 作为循环计数器。在这个循环中,您还有另一个表型循环,它也使用了i。由于屏幕选择是在每次外循环迭代开始时完成的,因此代码在这种情况下仍然有效,但一般来说,最好将循环计数器分开。

    【讨论】:

    • 拜托,我想知道您是如何添加屏幕标题以显示哪些屏幕正在实际绘制的。
    • 我现在修好了。由于使用了相同的循环计数器,它没有显示,但现在我更改了它并且效果很好。非常感谢!
    • @Maryam 您可以在每个循环中将main = paste("Screen", i) 添加到plot() 调用中,以在每个小图中显示屏幕编号。即:plot(PC_EPS$x, col=c(rep("red", f*Nums), rep("blue", f*Nums)), main = paste("Screen", i))
    • 是的,我使用了您之前通过使用不同的循环计数器丢弃的旁注,并且必须减去以使其与绘图相对应。 plot(PC_EPS$x, col=c(rep("red",fNums),rep("blue",fNums)), main= paste("EPS 模拟", (j- 2), 拆分 = ""))
    猜你喜欢
    • 1970-01-01
    • 2017-08-28
    • 1970-01-01
    • 2021-10-18
    • 2021-04-25
    • 1970-01-01
    • 2012-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多