【问题标题】:lm(formula) in R behaves differently within parLapplyR中的lm(公式)在parLapply中表现不同
【发布时间】:2019-03-27 21:00:25
【问题描述】:

首先我创建一对示例数据框:

df = data.frame("sample1" = runif(10), "sample2" = runif(10), "sample3" = runif(10), "sample4" = runif(10))
traits = data.frame("var1" = c(rep("group1", 2), rep("group2", 2)))
rownames(traits) = colnames(df)

如果我将公式创建为文本字符串,我可以将其直接插入 lm()

> row = t(df[1,])
> ModString = "row ~ traits$var1"
> Mod = lm(as.formula(ModString))
> Mod

Call:
lm(formula = as.formula(ModString))

Coefficients:
      (Intercept)  traits$var1group2  
           0.7799             0.1788  

但是如果我尝试对 parLapply 做同样的事情,我会收到一个错误,表明“traits”参数没有按预期工作:

> num_cores <- detectCores() - 1
> cl <- makeCluster(num_cores)
> results <- parLapply(cl = cl, seq(1:10), function(i, df, traits){
+     row = df[i,]
+     ModString = "vector ~ traits$factor1"
+     Mod = lm(ModString)
+     return(Mod)
+ }, df = df, traits = traits)
Error in checkForRemoteErrors(val) : 
  9 nodes produced errors; first error: object 'traits' not found

但奇怪的是,当我使用“特征”参数时,它正在进入 parLapply,这似乎与 lm() 的工作方式有关,这就是问题所在。我可以很好地输入和返回“特征”:

> cl <- makeCluster(num_cores)
> results <- parLapply(cl = cl, seq(1:10), function(i, df, traits){
+     row = df[i,]
+     traits2 = traits
+     ModString = "vector ~ traits$factor1"
+     return(list(traits2, row, ModString))
+ }, df = df, traits = traits)
> results
[[1]]
[[1]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[1]][[2]]
    sample1   sample2   sample3  sample4
1 0.6941108 0.8656177 0.9807334 0.936609

[[1]][[3]]
[1] "vector ~ traits$factor1"


[[2]]
[[2]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[2]][[2]]
    sample1   sample2   sample3   sample4
2 0.1007983 0.5599374 0.0208095 0.8082196

[[2]][[3]]
[1] "vector ~ traits$factor1"


[[3]]
[[3]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[3]][[2]]
    sample1   sample2  sample3   sample4
3 0.9633059 0.7564143 0.913617 0.4179525

[[3]][[3]]
[1] "vector ~ traits$factor1"


[[4]]
[[4]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[4]][[2]]
     sample1  sample2  sample3   sample4
4 0.06625104 0.390351 0.511572 0.8386714

[[4]][[3]]
[1] "vector ~ traits$factor1"


[[5]]
[[5]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[5]][[2]]
    sample1   sample2    sample3  sample4
5 0.6135228 0.4926991 0.08513074 0.105647

[[5]][[3]]
[1] "vector ~ traits$factor1"


[[6]]
[[6]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[6]][[2]]
    sample1   sample2   sample3   sample4
6 0.7121677 0.6554129 0.6409468 0.4906039

[[6]][[3]]
[1] "vector ~ traits$factor1"


[[7]]
[[7]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[7]][[2]]
    sample1  sample2   sample3   sample4
7 0.4651641 0.546514 0.4039608 0.1758802

[[7]][[3]]
[1] "vector ~ traits$factor1"


[[8]]
[[8]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[8]][[2]]
    sample1   sample2   sample3   sample4
8 0.5121237 0.4950444 0.9662431 0.6851582

[[8]][[3]]
[1] "vector ~ traits$factor1"


[[9]]
[[9]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[9]][[2]]
    sample1  sample2   sample3   sample4
9 0.2486208 0.135422 0.2128657 0.7332921

[[9]][[3]]
[1] "vector ~ traits$factor1"


[[10]]
[[10]][[1]]
          var1
sample1 group1
sample2 group1
sample3 group2
sample4 group2

[[10]][[2]]
      sample1   sample2   sample3   sample4
10 0.06203028 0.7916495 0.3528376 0.2259685

[[10]][[3]]
[1] "vector ~ traits$factor1"

我在这里遗漏了哪些令人尴尬的琐碎细节?

【问题讨论】:

  • 我对@9​​87654325@ 的经验很少,但我可以告诉您,您根本不应该使用$ 构建公式。该公式应包含data 参数中列的变量名称。例如lm(var1 ~ var2 + var3,data = my_data) 其中var1 等是my_data 中的所有列。
  • 如果我按名称索引也会发生同样的事情
  • 是的,问题在于您的基本方法以及数据组织的整体方式。在仍然将数据保存在两个不同的数据框中,其中一个以列作为行的情况下进行细微调整,这将变得非常复杂,以至于您会遇到很多问题。
  • 不幸的是,在我的情况下这是无法避免的,这只是我能做的最简单的例子。
  • 这是完全可行的,而且更干净......我会发布一个答案。

标签: r parallel-processing apply lm


【解决方案1】:

我会这样做;注意完全不同的数据组织:

library(dplyr)
library(tidyr)
library(tibble)
library(parallel)

#You seem to have rows of data that should be columns,
# this puts things in a form more suitable for work in R
df_new <- df %>% 
    mutate(row = 1:n()) %>% 
    gather(key = sample,value = val,sample1:sample4) %>% 
    arrange(row,sample)

#Data in rownames is not terribly useful
traits_new <- rownames_to_column(traits,"sample")

#Now we can put it all in *one* data frame
df_new <- left_join(df_new,
                    traits_new,
                    by = "sample")

#...and split it into a list representing each of the df's you
# want a lm() fit on
df_new_split <- split(df_new,df_new$row)

#Wrapper for lm with the only formula we need
fit_lm <- function(x){
    lm(val ~ var1,data = x)
}

num_cores <- detectCores() - 1
cl <- makeCluster(num_cores)

results <- parLapply(cl = cl,df_new_split,fit_lm)

【讨论】:

  • 谢谢,但我真的需要以这种方式组织数据,因为我在下游处理它。我真正的问题是为什么字符串在两种上下文中的解释不同。
  • @Thoughtcraft 原因是 bc lm() 并不是要以您的方式使用。在调用环境中查找的公式中传递变量名称的能力(第一次尝试如何工作)意味着简单的交互式工作,而不是编程。我展示的所有数据转换都可以在以后撤消。
  • 当然,但是为什么 lm 在 parLapply 之外使用相同的字符串和数据呢?这是我想弄清楚的。
  • @Thoughtcraft 因为当您不将事物拆分为多个进程时,R 具有用于在连续环境中查找名称的系统。即使那样,如果您在嵌套函数中执行此操作,事情也可能会出错。但是使用parLapply,我对每个进程可以从您的全局环境访问什么的假设为零。
  • @Thoughtcraft 访问和知道查看有两种不同的东西。当您进行traits2 &lt;- traits 之类的分配时,R 有一个查找traits 的过程,其中包括检查您所在函数的参数。但是请记住,一旦您调用lm(),您就已经下降了整个范围。那里发生的一切都在另一个全新的环境中。 lm 的工作方式是检查data 参数,然后检查调用环境;仅仅传递一个参数并不会在该环境中创建实际的参数。
【解决方案2】:

好吧,我觉得自己很傻,但我会留下这个问题,因为这是一个很好的例子,说明在复制粘贴和编辑多个版本的代码时很容易混淆。我在parLapply 中没有始终如一地使用as.formula,也忘记将变量名向量更改为行并转置它。

所以。以下工作只是花花公子:

require(parallel)
num_cores <- detectCores() - 1
cl <- makeCluster(num_cores)
results <- parLapply(cl = cl, seq(1:10), function(i, df, traits){
    row = t(df[i,])
    ModString = "row ~ traits[,\"var1\"]"
    Mod = lm(as.formula(ModString))
    return(Mod)
}, df = df, traits = traits)

【讨论】:

  • 不明白为什么这个答案没有用。这是我的问题的原因。虽然我不会与任何不赞成这个问题的人争论,因为它考虑得相当糟糕。
猜你喜欢
  • 2023-03-06
  • 1970-01-01
  • 2019-07-30
  • 2013-06-27
  • 2020-10-03
  • 2022-09-29
  • 1970-01-01
相关资源
最近更新 更多