【问题标题】:changing title of a plot inside a do.call在 do.call 中更改绘图的标题
【发布时间】:2013-08-02 07:23:49
【问题描述】:

函数 my.ccf 会生成一个绘图等。

my.ccf <- function(dat)
{
require(forecast)
modx <- auto.arima(dat[,1])
modx$series <- colnames(dat)[1]
mody <- Arima(dat[,2], model=modx)
mody$series <- colnames(dat)[2]
ccf1 <- ccf(residuals(modx), residuals(mody), type="correlation", ylab="CCF", 
            main=paste(colnames(dat)[1], "&", colnames(dat)[2], sep=" "))
return(list(modx=modx, mody=mody, ccf=ccf1))    
}
dat1 <- data.frame(p=rnorm(50), q=rnorm(50)); my.ccf(dat1) 

生成的图形以'p & x'等为标题

我正在使用函数 year.ccf 中的 do.call 将这个函数应用于另一个 data.frame (dat2)。首先,它将按年对传递的 data.frame 进行子集化(我有单独的函数来执行此操作。出于说明目的,我在此处使用 for 循环),然后将 my.ccf 应用于名为“x”的列与给定列的配对组合在 var.do. var.do 的长度从 3 到 9 不等。我必须在不同的数据帧上重复多次(超过 500 次)并尝试尽可能自动化。

year.ccf1 <- function(dat, var.do=c('a','b'))
{
year.form <- format(dat2$date, '%Y')
dat$year <- factor(year.form, levels=unique(year.form), ordered=TRUE)
yl <- levels(dat$year)
ydat <- list()
for(i in 1:length(yl))
ydat[[i]] <- subset(dat,year==yl[i])
wdat <- list()
for(i in 1:length(yl)){  
a <- list()
for(j in 1:length(var.do)){
#par(mfrow=c(2,2))
a[[j]] <- do.call(my.ccf, list(ydat[[i]][,eval(c(var.do[j],'x'))]))
}
names(a) <- var.do
wdat[[i]] <- a         
}
names(wdat) <- yl
return(wdat)
}
date <- seq(as.Date("2011/1/1"), as.Date("2013/8/1"),  by = "months")
dat2 <- data.frame(date=date,x =rnorm(length(date)), y=rnorm(length(date)),        
a=rnorm(length(date)),b=rnorm(length(date)))
pdf("./temp/dat2.pdf")
A <- year.ccf1(dat2, var.do=c('a', 'b'))
dev.off()

我正在尝试将 dat2.pdf 中每个图的标题更改为带有列名的年份标记,例如“2011 年:a 和 x 的 CCF”。不确定我是否遗漏了一些明显的东西或不明白如何在一个 do.call 中进行论证,如下所示。

do.call(my.ccf, main=paste("Year ", yl[i], var.do[j], " & x", sep=" "), list(ydat[[i]
[,eval(c(var.do[j],'x'))]))

还尝试将多个绘图放在一页中以使 pdf 文件更小。我尝试使用 par(mfrow)(未注释)来处理第二个问题,但失败了。

非常感谢任何帮助。

【问题讨论】:

    标签: r graphics cross-correlation do.call


    【解决方案1】:

    我认为你应该先给my.ccf 一个额外的参数。例如:

    my.ccf <- function(dat,year=NA)
    {
       ...
      title=paste(colnames(dat)[1], "&", colnames(dat)[2], sep=" ")
      if(!is.na(year))
        title <- paste('Year', year,': CCF',title)
      ccf1 <- ccf(residuals(modx), ..., main=title)
      .....
    }
    

    然后你把你的do.call 改成这样:

     do.call(my.ccf, list(dat=list(ydat[[i]][,eval(c(var.do[j],'x'))]),year=i))
    

    也就是说,认为您的 year.ccf1 函数过于复杂,而且您的效率极低。例如,尝试使用outermapply 重写它。

    year.ccf1 <- function(dat, var.do=c('a','b'))
    {
      dat$year <- factor(format(dat$date, '%Y'))
      ydat <- split(dat,dat$year)
      outer(names(ydat),var.do,function(x,y)
        Map(function(i,j)
            do.call(my.ccf, list(dat=ydat[[i]][,c(j,'x')],year=i))
               ,x,y)
      )
    }
    

    【讨论】:

    • 非常感谢您提供代码并让我变得高效。计算很好,但给出了错误消息“暗淡 [产品 6] 与对象 [18] 的长度不匹配”。这是由于使用了 outer() ,它期望长度应该是 18,但它返回一个 6 的列表。有解决这个问题的想法吗?我尝试了 lapply(),因为输入和输出都是列表,但也会产生其他错误。
    • 知道了! outer(...mapply(.....)),x,y, **SIMPLIFY=FALSE**)) 做的伎俩。每个组合的输出现在存储在一个列表中。
    • @ykh 好!我会更新我的答案,另一种选择是将mapply 替换为Map
    • 我需要收集足够的声望才能投票给你的答案。只要我有足够的声望,我就会这样做。 :-)
    • 我的版本和你的版本?我现在正在考虑这个问题。当您的版本正在运行时,将能够做到这一点。与此同时,我使用两个 foreach 循环获得了另一个版本。可能是所有三个方面的基准。
    猜你喜欢
    • 2014-10-14
    • 2017-12-11
    • 2016-09-13
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 2019-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多