【问题标题】:Vectorize which function to get positions向量化获取位置的函数
【发布时间】:2012-06-05 09:03:21
【问题描述】:

我有两个数据框(db1db2),我想在db2 中获得与db1 中的某些参数匹配的位置。这可以使用for 循环来实现,如下所示:

db1 &lt- data.frame(id=rep(1:4,each=4),
                  class=sample(1:10, 16, replace=TRUE),
                  var=rnorm(16)
                  )
db2 &lt- expand.grid(id=1:4, class=1:10)
db2$x &lt- rnorm(nrow(db2))

for(i in 1:nrow(db1)) print(which(db2$id==db1$id[i] & db2$class==db1$class[i]))

但是循环非常低效,所以我想对这个循环进行矢量化。可以将向量传递给which() 函数,以便该函数在 db2 中搜索 db1 中的每个值?

【问题讨论】:

  • 拥有这些职位后,您想如何处理这些职位?换句话说;有没有比上面最初的要求更大的目的?顺便说一句,如果您通过为结果对象分配存储空间并在循环时填充该对象来正确设置循环,那么循环在 R 中并不是低效的。
  • 获得位置后,我的目的是从db2 中收集位置(+/- n 个位置)周围的一系列数据,并将它们添加到db1 数据集中。我认为我的实际问题是 db1 (3x10^6 obs) 和 db2 (1x10^6 obs) 都很大。

标签: r vectorization data.table


【解决方案1】:
library(data.table)
db1 <- data.table(db1)
db2 <- data.table(db2)
# You can index by additional columns as necessary
setkeyv(db1, c("id","class"))
setkeyv(db2, c("id","class"))

# Show only records in db2 that match id and class with db1

db2[db1,]

      id class           x         var
 [1,]  1     1 -0.50266835  0.82391749
 [2,]  1     9 -1.21245991 -1.43163848
 [3,]  1     9 -1.21245991 -0.68622189
 [4,]  1    10 -0.28659235 -0.98107793
 [5,]  2     4  2.18779836  1.25841256
 [6,]  2     6  1.32407301  0.42287395
 [7,]  2     7 -0.53808409 -0.12069089
 [8,]  2    10 -0.67679146 -0.73930821
 [9,]  3     7  0.03133591  0.31142901
[10,]  3     8  0.78927215  1.86952233
[11,]  3     9 -0.04674115 -0.45102021
[12,]  3    10 -0.83388764 -0.04354332
[13,]  4     8  1.17608109 -0.07343352
[14,]  4     8  1.17608109 -0.00053299
[15,]  4     9  0.59344187 -0.21407897
[16,]  4    10 -2.06237055  0.78420146

# To just return an index of matching rows
db2[db1, which=T]

 [1]  1  9  9 10 14 16 17 20 27 28 29 30 38 38 39 40

# To get only unique row indices
> db2[unique(db1),which=T]
[1]  1  9 10 14 16 17 20 27 28 29 30 38 39 40

【讨论】:

    【解决方案2】:

    如果 db1 和 db2 的行数相同,则打印 db2 和 db1 'id, class' 相等的所有 db2 行:

    print(db2[db2$id == db1$id & db2$class == db1$class,])
    

    按 db2$id 排序的同一个查询:

    print(db2[order(db2[db2$id == db1$id & db2$class == db1$class,]$id, decreasing = TRUE))
    

    【讨论】:

    • 我认为您误解了这个问题。你的提议类似于merge:merge(db1, db2, by=c("id","class"))。此外,您的提案不起作用,因为 db1db2 的大小不同。
    • 查询只打印 db2 行,它不合并 2 个数据帧。但是,如果它们的尺寸不同,它将无法正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-22
    • 1970-01-01
    • 2017-10-19
    相关资源
    最近更新 更多