如何根据成对向量的值 select 一行?

How to select a row based on values from paired vectors?

我有一个名为 dat 的数据框,它看起来像这样:

   id1  id2            value
1     3    0 8.00019752415226
2     4    0 27.4861843945884
3     0    3 8.00019752415226
4     4    3 20.1582815171649
5     0    4 27.4861843945884
6     3    4 20.1582815171649
7     1    2                0
8     2    1                0

id1和id2可以取0到4的值,是被试的id号,取值是每个被试之间的欧氏距离。

现在我有了一个矩阵,它是通过一次取 2 个 id 变量(基本上 c(0,1,2,3,4))的唯一元素的所有可能组合得到的:

combn(dat$id,2)

给出输出:

>           [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
>     [1,]    0    0    0    0    1    1    1    2    2     3
>     [2,]    1    2    3    4    2    3    4    3    4     4

现在我想根据这个矩阵的每一列在 dat 中 select 行,即 select 带有 (id1 = 0, id2 = 1) 的行; (id1= 0, id2 = 2); (id1 = 0, id2 = 3) 等等,然后用它们制作一个数据框。

现在我可以使用 for 循环轻松地实现它,但我想知道是否有更快更优雅的方法来使用矢量化函数来实现它。提前致谢!

这样做:


dat <- read.table(text=
"   id1  id2            value
1     3    0 8.00019752415226
2     4    0 27.4861843945884
3     0    3 8.00019752415226
4     4    3 20.1582815171649
5     0    4 27.4861843945884
6     3    4 20.1582815171649
7     1    2                0
8     2    1                0
", header=TRUE )

look.up <- combn(0:4,2) %>% t %>%
    as.data.frame %>%
    setnames( paste0("id",1:2) )

look.up %>% left_join( dat, on=colnames(look.up) )

输出:


Joining, by = c("id1", "id2")
   id1 id2     value
1    0   1        NA
2    0   2        NA
3    0   3  8.000198
4    0   4 27.486184
5    1   2  0.000000
6    1   3        NA
7    1   4        NA
8    2   3        NA
9    2   4        NA
10   3   4 20.158282

从本质上将组合转换为与您的数据匹配的 2 列 data.frame,并执行 join 以获取基于两列的值列。

虽然你的 dat$id 不可用,但我用 combn(0:4, 2) 创建了我的 combn(0:4, 2),你可以用以下语法中的 combn(dat$id, 2) 替换

purrr::map(as.data.frame(combn(0:4, 2)), ~ dat[dat$id1 == .[1] & dat$id2 == .[2],])

$V1
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V2
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V3
  id1 id2    value
3   0   3 8.000198

$V4
  id1 id2    value
5   0   4 27.48618

$V5
  id1 id2 value
7   1   2     0

$V6
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V7
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V8
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V9
[1] id1   id2   value
<0 rows> (or 0-length row.names)

$V10
  id1 id2    value
6   3   4 20.15828

如果您想将每个组合作为列表中的单独项目,以上代码将起作用。但是,如果你想结合所有这些,只需使用 map_dfr 而不是 map

purrr::map_dfr(as.data.frame(combn(0:4, 2)), ~ dat[dat$id1 == .[1] & dat$id2 == .[2],])

  id1 id2     value
3   0   3  8.000198
5   0   4 27.486184
7   1   2  0.000000
6   3   4 20.158282