【问题标题】:Putting code chunk in an if statement changes assigning behavior R将代码块放在 if 语句中会更改分配行为 R
【发布时间】:2019-06-17 08:24:22
【问题描述】:

我遇到了一个非常奇怪的 R 问题。我在分配列表元素的if 语句中有一段代码,但无论它是在if 语句内(即使if 语句是if (1==1) {...})还是在它之外运行,都会有不同的反应。

基本上,代码应该只是在做if (true) {Raw[[1]]$params=params[[1]]; Raw[[2]]$params=params[[2]]; etc..},但最后是Raw[[1]]$params==Raw[[2]]$paramsRaw[[3]]$params==Raw[[4]]$params,但只有如果它在@987654327中@ 陈述。如果它不在if 语句中,它可以正常工作。

让我举个例子(这是原始代码的一个大大简化的版本;rep 和列表分配的动机是出于与问题无关的变量管理原因):

#----- Create variables
# params is a 4-element list
params0 <- list(runif(2),runif(4),runif(6),runif(8))
# Raw is a 2-element list, of which every element is another (named) list
Raw0 <- list(list(data=runif(3),params=runif(2)),
             list(data=runif(6),params=runif(6)))

dothing <- TRUE

#----- With if statement - does not correctly assign
Raw <- Raw0
params <- params0

if (dothing) {
  Raw <- rep(Raw,each=2)
  for (x in seq(1,length(params))) {
    Raw[[x]]$params <- params[[x]]
  }
}

# This should be false since params[[1]] ~= params[[2]], but returns true 
identical(Raw[[1]],Raw[[2]])

#----- Without if statement - does correctly assign
Raw <- Raw0
params <- params0

Raw <- rep(Raw,each=2)
for (x in seq(1,length(params))) {
  Raw[[x]]$params <- params[[x]]
}

# This returns false as expected
identical(Raw[[1]],Raw[[2]])

所有这一切的最后一个非常奇怪的皱纹 - 在原始代码中,如果代码逐块运行(不丢失任何行),分配工作正常,但如果整个代码运行则分配不正确立刻。

谁能告诉我我在这里缺少什么?提前感谢您的帮助!

【问题讨论】:

  • (你使用的是什么 IDE?)当我运行你的第一个块(通过dothing &lt;- TRUE),然后运行第二个块(使用if)时,我得到了FALSE。当我将源代码块作为一个整体运行时,我会像你一样得到TRUE。我在 emacs/ess 中这样做,所以它可能与块排序和变量的可见性有关。很有趣。
  • 我正在使用 RStudio - 是的,我认为它最初可能是从 SublimeText 传输命令时出现的问题,但后来我在 RStudio 中用同样的问题至少重写了这个块。 ..
  • 再次运行您的代码,将Raw &lt;- rep(Raw,each=2) 替换为assign('Raw', rep(Raw, each=2))。我相信 R 会将for loop 中的数据分配给缓存环境,然后在返回R_GlobalEnv 时将其丢失。所以在identical(Raw[[1]],Raw[[2]]) 中,真正被比较的Raw 变量来自Raw &lt;- rep(Raw,each=2)
  • 进一步......如果你在循环开始之前用(不是“to”)Raw(例如,str(Raw) 紧接在 if 之前)做了 something 它现在按预期工作。这表明它不一定(或“只是”){ } 环境(尽管它仍然可能是其中的一部分)。 (它似乎是特定的......invisible(Raw)Raw 而不是 str(Raw) 确实工作,head(Raw)does。)
  • @ks905383 是否解决了您的问题,您在哪里寻找其他东西?

标签: r list if-statement assign


【解决方案1】:

观察到的行为与if 循环无关。 如果您分配不同的结构,它将引发警告“要替换的项目数不是替换长度的倍数”。 我认为没有 - 在你的情况下 - 使用 $ 访问 Raw 内容并替换为 params 的内容。

> str(Raw[[1]]$params)
 num [1:2] 0.925 0.393
> str(params[[1]])
 num [1:2] 0.177 0.986

#returns the content
> str(Raw[[1]]$params)  #Used in your eg
 num [1:2] 0.949 0.143
> str(Raw[[1]][[2]])    #Equivalent to the one used in your eg
 num [1:2] 0.949 0.143

#returns the type of list 
> str(Raw[[1]]["params"])
List of 1
 $ params: num [1:2] 0.949 0.143

区别在于Raw[[1]]["params"] 返回list,而Raw[[1]]$paramsRaw[[1]][[2]] 返回内容。

但实际上,当一个相同大小和类型的列表被替换为另一个列表(这是替换长度的正确倍数)时,这会起作用。

更新代码:

#----- Create variables
# params is a 4-element list
params0 <- list(runif(2),runif(4),runif(6),runif(8))
# Raw is a 2-element list, of which every element is another (named) list
Raw0 <- list(list(data=runif(3),params=runif(2)),
             list(data=runif(6),params=runif(6)))

dothing <- TRUE

#----- With if statement - does not correctly assign
Raw <- Raw0
params <- params0

if (dothing) {
  Raw <- rep(Raw,each=2)
  for (x in seq(1,length(params))) {
    Raw[[x]]["params"] <- params[x]      ##Note the way list is returned and list is replaced for another list.
  }
}

#CORRECTED returns false: This should be false since params[[1]] ~= params[[2]], but returns true
identical(Raw[[1]],Raw[[2]])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多