r语言 - 带有矩阵参数的奇怪括号赋值调用('[<-')



最近我偶然发现了这段代码:

y <- NULL
y[cbind(1:2, 1:2)] <- list( list(1,2), list(2,3))

从这里的第二个答案来看。

但它似乎与y <- list(...)没有什么不同,正如下面的比较所示:

> identical(y, list( list(1,2), list(2,3)))
[1] TRUE
> identical(y, y[cbind(1:2, 1:2)])
[1] FALSE

括号里的作业是怎么回事?为什么它不抛出错误?为什么它与最后一行代码中的非赋值版本不同?

矩阵索引仅在y变暗时适用将其与标准的R循环以及所有矩阵实际上都是向量的事实结合起来,这种行为是有意义的。

当您将y初始化为NULL时,您可以确保它没有dim。因此,当你用矩阵(比如ind)对y进行索引时,你会得到与调用y[as.vector(ind)] 相同的结果

identical(y[ind], y[as.vector(ind)])
# [1] TRUE

如果ind中存在重复值,并且您也在分配,则对于每个索引,将只保留分配给它的最后一个值。例如,假设我们正在执行

y <- NULL; y[cbind(1:2, 2:1)] <- list( list(1,2), list(3,4) )
#   y has no dimension, so `y[cbind(1:2, 2:1)]` 
#   is the equivalent of   `y[c(1:2, 2:1)]`

当你分配y[c(1, 2, 2, 1)] <- list("A", "B")时,实际上发生的情况类似于:

    y[[1]] <- "A"
    y[[2]] <- "B"
    y[[2]] <- "B"  # <~~ 'Overwriting' previous value 
    y[[1]] <- "A"  # <~~ 'Overwriting' previous value 

以下是对发生的索引的进一步观察:(注意前两个字母是如何重复的)

ind <- cbind(1:2, 1:2)
L <- as.list(LETTERS)
L[ind]
# [[1]]
# [1] "A"
# 
# [[2]]
# [1] "B"
# 
# [[3]]
# [1] "A"
# 
# [[4]]
# [1] "B"

这是同样的事情,现在是任务请注意,只有第三个和第四个赋值被保留了

L[ind] <- c("FirstWord", "SecondWord", "ThirdWord", "FourthWord")
L[ind]
# [[1]]
# [1] "ThirdWord"
# 
# [[2]]
# [1] "FourthWord"
# 
# [[3]]
# [1] "ThirdWord"
# 
# [[4]]
# [1] "FourthWord"

尝试不同的索引以获得进一步的清晰度:

ind <- cbind(c(3, 2), c(1, 3))  ## will be treated as c(3, 2, 1, 3) 
L <- as.list(LETTERS)
L[ind] <- c("FirstWord", "SecondWord", "ThirdWord", "FourthWord")
L[1:5]
#  [[1]]
#  [1] "ThirdWord"
#  
#  [[2]]
#  [1] "SecondWord"
#  
#  [[3]]
#  [1] "FourthWord"
#  
#  [[4]]
#  [1] "D"
#  
#  [[5]]
#  [1] "E"
L[ind]
#  [[1]]
#  [1] "FourthWord"
#  
#  [[2]]
#  [1] "SecondWord"
#  
#  [[3]]
#  [1] "ThirdWord"
#  
#  [[4]]
#  [1] "FourthWord"

编辑关于@agstudy的问题:

查看[的src,我们有以下评论:

  • 特殊[下标,其中dim(x)==ncol(下标矩阵)
  • 在VectorSubset内部处理。下标矩阵被翻转
  • 转换为适当大小的下标向量,然后
  • VectorSubset继续

查看函数static SEXP VectorSubset(SEXP x, SEXP s, SEXP call),相关检查如下:

/* lines omitted */ 
attrib = getAttrib(x, R_DimSymbol);
/* lines omitted */
if (isMatrix(s) && isArray(x) && ncols(s) == length(attrib)) {
    /* lines omitted */
...

最新更新