2

我还是 R.. 的新手..并且已经阅读过以前的类似帖子...我认为这与 r 传递承诺但不传递值的事实有关,但我不太清楚这里哪里出错了..

这是我想尝试的代码的简单版本:

定义:

data<-data.frame(TYPE=as.integer(runif(20,1,3)),COL1=runif(20,1,100),COL2=runif(20,1,10))
RULEA=10
RULEB=20

我运行如下:

f<-function(data,metric="A"){
  data<-ddply(data,.(TYPE),transform,SUMCOL1=sum(COL1,na.rm=TRUE),SUMCOL2=sum(COL2,na.rm=TRUE))
  data1<-f1(data=data,metric=metric)
  return(data1)
}

f1<-function(data=data,metric="A"){
  if(metric=="A"){
    RULE<-RULEA
    data$FACTOR<-data$COL1
  }else if(metric=="B"){
    RULE<-RULEB
    data$FACTOR<-data$COL1
  }
  if(nrow(data!=0)){
    x<-subset(data,FACTOR>1)
    if(nrow(x)!=0){
      x<-ddply(x,.(TYPE),mutate,sig=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE)
    }
  }

 return(x)
}

如果我运行如下: f(data,metric="A")

它会给我结果:

> f(data,metric="A")
Error in eval(expr, envir, enclos) : object 'RULE' not found

我不知道为什么它找不到“规则”......?感谢您的帮助!

4

3 回答 3

2

根据这个(旧的)讨论,这实际上是一个非常具有挑战性的问题。

正如该讨论所指出的那样,当您到达评估表达式的地步时mutateddply已移交给ldply已移交给的llply。现在mutate必须弄清楚该表达式中的所有内容来自何处。似乎没那么简单。

一种(一种可怕的)解决方法是更改RULE​​使用的分配<<-。Hadley 在那次讨论中提到编写一个显式函数,这可能是一个更安全的选择。

于 2013-04-03T21:40:28.097 回答
2

也许我在这里遗漏了一些东西,但RULE如果它是以下内容的一部分,则会被评估data.frame x

f1<-function(data=data,metric="A"){
  if(metric=="A"){
    # RULE<-RULEA
    data$RULE<-RULEA
    data$FACTOR<-data$COL1
  }else if(metric=="B"){
    # RULE<-RULEB
    data$RULE<-RULEB
    data$FACTOR<-data$COL1
  }
  if(nrow(data!=0)){
    x<-subset(data,FACTOR>1)
    if(nrow(x)!=0){
      x<-ddply(x,.(TYPE),mutate,sig=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE)
    }
  }
  return(x)
}

f(data,metric="A")
#    TYPE      COL1     COL2  SUMCOL1  SUMCOL2 RULE    FACTOR  sig
# 1     1 43.983597 9.457873 496.6858 60.05813   10 43.983597 TRUE
# 2     1 60.438590 4.196161 496.6858 60.05813   10 60.438590 TRUE
# 3     1 20.251421 6.780956 496.6858 60.05813   10 20.251421 TRUE

我是基地的粉丝,所以我可能会重写你的函数ff1就像这样:

f<-function(data=data,metric='A'){
  b<-by(data,data$TYPE, function(x)
    data.frame(max=max(x$COL1),min=min(x$COL1),SUMCOL1=sum(x$COL1),SUMCOL2=sum(x$COL2)))
  m<-do.call(rbind,b)
  m$TYPE<-rownames(m)
  m$sig<-m$max>(2*m$min) & m$min < switch(metric,A=RULEA,B=RULEB)
  merge(data,m)[,c(names(data),'SUMCOL1','SUMCOL2','sig')]
}


f(data,metric='A')
于 2013-04-03T21:58:00.520 回答
2

这是一种data.table可能有用的方法,因为它避免了这个问题。

请注意,我在每个函数中显式复制 data.tables,以使函数的行为更像常规 R 函数 - 因此我并没有真正利用 data.table 内存效率,而是它的评估方式j很好(它会比ddply) 快。

一般来说,会有一种更 data.table糟糕的方式来做你想做的事,而这个答案并不是真的要那样做。

f<-function(DT,metric="A"){
  ## explicit copy to avoid assignment in global `DT`
  dd <- copy(DT)
  ## add sum columns to local copy
  dd[, c('SUMCOL1', 'SUMCOL2') := lapply(.SD, sum ,na.rm = TRUE),by = 'TYPE', .SDcols = c('COL1','COL2')]
  # do f1 on dd
  dd1<-f1(DT = dd,metric=metric)
  # return results
  return(dd1)
}


f1<-function(DT,metric="A"){
  ## explicit copy
  ddd <- copy(DT)
  # assign RULE (a bit simpler)
  RULE <-  switch(metric, 'A' = RULEA, 'B' = RULEB)
  # i FACTOR didn't depend on metric
  ddd[, FACTOR := COL1]
  # subset
  x <- ddd[FACTOR >1, ]

  x[, sig :=(max(FACTOR)>2*min(FACTOR)) & min(FACTOR) < RULE ,by = 'TYPE']
  return(x)
}

f(data.table(data),metric="A")
于 2013-04-03T23:13:03.140 回答