赋值给具有重复索引的矩阵的子集

时间:2014-03-10 16:04:57

标签: r subset

不确定这是否有资格获得R-Inferno中的条目,但有人可以评论以下替代方式背后的逻辑吗?

foo<-matrix(1:6,2)
bar<-foo[2,c(1,3,1)]
bar
# [1] 2 6 2
foo[2,c(1,3,1)]<-foo[2,c(1,3,1)]+5
foo
#      [,1] [,2] [,3]
# [1,]    1    3    5
# [2,]    7    4   11

我的问题是:生成bar时,重复的坐标会在输出中产生重复的元素,但在修改foo时,重复的坐标会导致重复的加法操作。 (相比之下,for(j in c(1,3,1) ) foo[2,j]<-foo[2,j]+5确实如此)。为什么&amp; [<-究竟如何忽略重复索引?

2 个答案:

答案 0 :(得分:5)

来自help("[<-")

  

子分配是按顺序完成的,因此如果指定的索引更多   而不是一次索引的最新指定值。

foo<-matrix(1:6,2)

foo[1,rep(1,2)] <- c(1,42)

#     [,1] [,2] [,3]
#[1,]   42    3    5
#[2,]    2    4    6

答案 1 :(得分:1)

试图间接回答评论中的次要问题:

> vec <- 1:10
> microbenchmark(
+       rep(1, 1e4),
+       vec[rep(1, 1e4)] <- 1:1e4,
+       vec[1] <- 1e4
+     )
Unit: microseconds
                          expr     min       lq   median       uq      max neval
                 rep(1, 10000)  16.457  17.9190  18.2860  19.0170 2561.327   100
 vec[rep(1, 10000)] <- 1:10000 215.395 219.7835 227.8285 233.6795 3437.532   100
               vec[1] <- 10000   1.463   2.1950   3.2920   3.8405   22.308   100

强烈建议将相同的值一遍又一遍地分配给相同的内存位置,直到只有最后一个占优势。为什么不添加它们只是因为这里的操作是覆盖,而不是添加(尽管这可能不是你所要求的“不会导致重复的添加操作”)。

请注意,您的循环和直接分配不等同,因为在循环中您正在阅读,添加,分配,重新阅读,重新添加,重新分配等,而在您的直接分配中,您正在阅读一次,将单个向量添加一次,然后仅通过覆盖保留最后一个值。

“读取”之间的关键区别在于,预期的“输出”是索引向量的向量长度,而“写入”的长度(不包括使用越界索引的情况)向量的长度受到你写的矢量的限制。