在Linux函数中使用tm:bug分配R函数中的全局变量?

时间:2015-01-14 15:32:10

标签: linux r global-variables tm

在R中使用包tm,我想用一个非常复杂的函数转换语料库,我需要一些副作用来存储相关信息。由于content_transformer需要特定的函数格式,因此简单的方法是在我的函数中使用<<-。下面的代码出现问题:

library(tm)
a <- 4
n <- 2
corp<-VCorpus(VectorSource(rep("fish",n)))
(func<-content_transformer(
  function(x) {
    a <<- 42
    return(x)
}))
corp<-tm_map(corp,func)
print(a)

它打印错误的答案,即4.但是当n = 1时,它打印出正确的答案。所以我认为这是多线程,tm不能表现为标量R.我想这是一个bug,因为在Windows上,它的工作原理。 (注意:我在Linux上使用R 3.1.2,在Windows上使用R 3.1.1。)

问题:这是一个错误吗?如果是的话,一个已知的bug?是否有一个简单的解决方案,不需要重构代码?

谢谢!


编辑:使用assing的其他示例

rm(list=ls())
library(tm)
env <- new.env()
a <- 1
n <- 2
corp<-VCorpus(VectorSource(rep("fish",n)))
(func<-content_transformer(
  function(x,e) {
    assign("a", 42, envir=e)
    print(e)
    print(ls.str(e))
    return(x)
}))
corp<-tm_map(corp,func,env)
print(env)
print(ls.str(env))

1 个答案:

答案 0 :(得分:2)

事实上,这在Windows下无意中起作用,因为mclapply未在Windows下定义,而只是调用lapply

的确,当你打电话给tm_map时,你正在使用这个功能:

tm:::tm_map.VCorpus
function (x, FUN, ..., lazy = FALSE) 
{
    if (lazy) {
        fun <- function(x) FUN(x, ...)
        if (is.null(x$lazy)) 
            x$lazy <- list(index = rep(TRUE, length(x)), maps = list(fun))
        else x$lazy$maps <- c(x$lazy$maps, list(fun))
    }
    else x$content <- mclapply(content(x), FUN, ...) ## this the important line
    x
}

因此,您可以通过调用mclapply

来重现“奇数/正常”行为
library(parallel)
res <- mclapply(1:2, function(x){a<<- 20;x})

a
[1] 4

a未改变且仍然等于4.这是正常的并列行为,因为我们避免产生副作用。在mcapply下,只需调用lapply,即可正确更改全局变量的值。

伪解决方案

如果您想要全局副作用,最好使用lapply,但如果您将a作为第二个参数添加到函数中,您可以在阅读中模拟全局变量... < / p>

func <- 
  function(x,a) {   
    a <- 42      ## use a here 
    x$a <- a     ## assign it to the x environment 
    return(x)    ## but the new value of a can not be used by others documents..
  }
(Func<-content_transformer(func))
res <- tm_map(corp,Func,a=4)