R:下标赋值不覆盖值,或更改所有值(半算出来)

Posted

技术标签:

【中文标题】R:下标赋值不覆盖值,或更改所有值(半算出来)【英文标题】:R: Subscripted assignments not overwriting values, or changing all values (halfway figured out) 【发布时间】:2020-05-30 19:24:57 【问题描述】:

我的 R 代码中不时出现问题,我将尝试使用下标赋值覆盖变量的值,并且部分/所有值不会被覆盖。 (我已经弄清楚了问题的一半,但问题的后半部分仍然适用。)

这是代码的简化示例,它比较两个变量以查看哪个更大,然后找到它们相等的位置并将“更大”变量设置为 -1 以指示两者都不是更大。

a <- rep(0:2,96)
b <- rep(0:3,72)
dataset <- data.frame(cbind(a,b))
dim(dataset) # Show dimensions

> [1] 288   2

# Add a few random NAs
dataset$a[15] <- NA
dataset$b[27] <- NA
dataset$a_bigger <- (dataset$a > dataset$b)
dataset$b_bigger <- (dataset$b > dataset$a)
table(dataset[,c('a_bigger','b_bigger')],useNA='ifany')

>        b_bigger
>a_bigger FALSE TRUE <NA>
>   FALSE    70  144    0
>   TRUE     72    0    0
>   <NA>      0    0    2

dataset$same <- (dataset$a == dataset$b) # Find values where they are the same and neither is bigger
table(dataset$same,useNA='ifany') # Show that there are NAs in dataset$same.

> FALSE  TRUE  <NA>
>  216    70     2

dataset$same[is.na(dataset$a) | is.na(dataset$b)] <- 0 # Fix the NAs. A and B can't be the same if one of them is NA.
table(dataset$same,useNA='ifany') # Show that there are no longer NAs

>   0   1
> 218  70

dataset$a_bigger[dataset$same] <- -1
dataset$b_bigger[dataset$same] <- -1
table(dataset[,c('a_bigger','b_bigger')],useNA='ifany') # Wait, there should be 70 changed, not 1...?

>         b_bigger
> a_bigger  -1   0   1 <NA>
>    -1     1   0   0    0
>    0      0  69 144    0
>    1      0  72   0    0
>    <NA>   0   0   0    2

到目前为止,我已经弄清楚发生了什么。将一些“相同”值设置为 0 将其从逻辑真/假更改为 0/1,然后当我用它来索引另一个变量时,“1s”被认为是“覆盖第一行”而不是逻辑正确。

这让我感到困惑,因为在其他情况下,R 将 0/1 视为等同于真/假(事实上,如果我将赋值行重写为 dataset$a_bigger[dataset$same &amp; dataset$same] &lt;- -1,则可以)但在至少我能理解现在发生的事情。

但我还是不明白为什么会这样:

dataset$even_weirder[dataset$same] <- -1 # But now if I do the assignment on a column/variable that's not initialized...
table(dataset[,'even_weirder'],useNA='ifany') # They all change!!!

>  -1
> 288

如果它真的认为当我写 dataset$somevar[dataset$same] 时我指的是位置 0(它会忽略)和位置 1(它会一遍又一遍地覆盖),那么当我使用未初始化的列执行此操作时,为什么会这样做将 -1 分配给每一行,而不是将其分配给第一行并留下其余的 NA?

【问题讨论】:

【参考方案1】:

问题基本上是

class(dataset$same)
#[1] "numeric"

不是逻辑的,而是二进制的,即 0 和 1

head(dataset$same)
#[1] 1 1 1 0 0 0

应该是

as.logical(dataset$same)

因为赋值发生在索引位置 1,即值 -1 在第一个元素上得到更新,而不是在其他任何地方

dataset$a_bigger[as.logical(dataset$same)] <- -1
dataset$b_bigger[as.logical(dataset$same)] <- -1

table(dataset[,c('a_bigger','b_bigger')],useNA='ifany')
#        b_bigger
#a_bigger  -1   0   1 <NA>
#    -1    70   0   0    0   #### 70 is showing up now
#    0      0   0 144    0
#    1      0  72   0    0
#    <NA>   0   0   0    2

关于“even_weider”,它是动态创建的,因此当它被分配给-1 时,第一个元素会被回收到列的整个长度

dataset$even_weirder[dataset$same]
#NULL
dataset$even_weirder[dataset$same] <- -1
sum(dataset$same)
#[1] 70
table(dataset[,'even_weirder'],useNA='ifany')

# -1 
#288 
dataset$even_weirder
#  [1] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
# [39] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
# [77] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
#[115] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
#[153] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
#[191] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
#[229] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
#[267] -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1

【讨论】:

谢谢!我现在明白那部分了,但我还没有弄清楚的是底部未初始化的列,而不是认为“1”是指第 1 行,而是写入每一行。我知道 0/1 不是在这里起到逻辑作用,但它们似乎也没有起到数字索引的作用(至少在第二部分中),我很好奇它在做什么! @TiredSquirrel 考虑一下v1 &lt;- c(1, 2, 3, 4, 5); i1 &lt;- c(1, 0, 1, 0, 1); v1[i1] &lt;- -1 该值仅更改了v1# [1] -1 2 3 4 5,因为 1 是。仅提及它的位置,不考虑 0,因为 R 索引从 1 开始 在这部分中,似乎认为我的 0 和 1 指的是第 1 行以外的行:dataset$even_weirder[dataset$same] &lt;- -1table(dataset[,'even_weirder'],useNA='ifany') 显示了 288 个 -1 实例,而不是一个 -1 和 287不适用。

以上是关于R:下标赋值不覆盖值,或更改所有值(半算出来)的主要内容,如果未能解决你的问题,请参考以下文章

Object.assign() 保留所有未更改的值[重复]

python基础——持续更新中

R - 如果在列表中找不到,则更改值

带下标运算符的重载赋值运算符

关键字 修饰符

代码检查错误列表