【问题标题】:How to select a row based on values from paired vectors?如何根据配对向量中的值选择一行?
【发布时间】:2021-03-26 09:58:31
【问题描述】:

我有一个名为 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 中的行,即选择具有 (id1 = 0, id2 = 1); 的行(id1=0,id2=2); (id1 = 0, id2 = 3) 等等,然后用它们制作一个数据框。

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

【问题讨论】:

    标签: r filter subset combinations


    【解决方案1】:

    这样做:

    
    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 以获取基于两列的值列。

    【讨论】:

      【解决方案2】:

      虽然您的dat$id 不可用,但我使用combn(0:4, 2) 创建了我的combn(dat$id, 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
      

      【讨论】:

      • 非常感谢!尽管您的答案只是一行代码(更简单,更优雅!),但它需要一个单独的包,而另一个答案似乎更直观。也非常感谢您向我介绍这个包 (purr)。
      猜你喜欢
      • 2012-07-21
      • 2015-02-10
      • 1970-01-01
      • 1970-01-01
      • 2010-12-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多