如何根据成对向量的值 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
我有一个名为 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