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 & dataset$same] <- -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 <- c(1, 2, 3, 4, 5); i1 <- c(1, 0, 1, 0, 1); v1[i1] <- -1
该值仅更改了v1# [1] -1 2 3 4 5
,因为 1 是。仅提及它的位置,不考虑 0,因为 R 索引从 1 开始
在这部分中,似乎认为我的 0 和 1 指的是第 1 行以外的行:dataset$even_weirder[dataset$same] <- -1
和 table(dataset[,'even_weirder'],useNA='ifany')
显示了 288 个 -1 实例,而不是一个 -1 和 287不适用。以上是关于R:下标赋值不覆盖值,或更改所有值(半算出来)的主要内容,如果未能解决你的问题,请参考以下文章