如何避免 matrix/dataframe 作为 R 中的元素通过管道 (%>%) 进入列表

How to avoid matrix/dataframe being piped (%>%) into list as an element in R

我想根据数据框创建相关矩阵和协方差矩阵列表。我尝试使用 magrittr 管道运算符 (%>%) 将数据帧传输到列表中,如下例所示。问题是数据框本身作为第一个列表元素插入。我知道管道运算符的默认行为是将对象注入到它通过管道传输到的函数的第一个位置。但是,我很想知道是否有一种简单的方法可以将 matrix/dataframe 通过管道传输到列表中的函数中,同时避免插入数据帧本身?

代码示例:

library(magrittr) # alternatively 'dplyr'

matrix(1:27, ncol = 6) %>% as.data.frame() %>%
list(
    a = list(
        cor(.[,1:3]),
        cov(.[,1:3])
    ),
    b = list(
        cor(.[,4:6]),
        cov(.[,4:6])
    )
)

输出:

[[1]]                          # I want to avoid inserting the 
A data.frame: 4 × 4            # dataframe as an element
V1  V2  V3  V4
<int>   <int>   <int>   <int>
1   5   9   13
2   6   10  14
3   7   11  15
4   8   12  16

$a
   A matrix: 2 × 2 of type dbl
   V1   V2
   V1   1   1
   V2   1   1

   A matrix: 2 × 2 of type dbl
   V1   V2
   V1   1.666667    1.666667
   V2   1.666667    1.666667

$b
   A matrix: 2 × 2 of type dbl
   V3   V4
   V3   1   1
   V4   1   1

   A matrix: 2 × 2 of type dbl
   V3   V4
   V3   1.666667    1.666667
   V4   1.666667    1.666667

只需将 extract 添加到您的管道中即可获得没有第一个元素的结果:

library(magrittr)

matrix(1:30, ncol = 6) %>% as.data.frame() %>%
list(
    a = list(
        cor(.[,1:3]),
        cov(.[,1:3])
    ),
    b = list(
        cor(.[,4:6]),
        cov(.[,4:6])
    )
) %>%
  extract(-1)
#> $a
#> $a[[1]]
#>    V1 V2 V3
#> V1  1  1  1
#> V2  1  1  1
#> V3  1  1  1
#> 
#> $a[[2]]
#>     V1  V2  V3
#> V1 2.5 2.5 2.5
#> V2 2.5 2.5 2.5
#> V3 2.5 2.5 2.5
#> 
#> 
#> $b
#> $b[[1]]
#>    V4 V5 V6
#> V4  1  1  1
#> V5  1  1  1
#> V6  1  1  1
#> 
#> $b[[2]]
#>     V4  V5  V6
#> V4 2.5 2.5 2.5
#> V5 2.5 2.5 2.5
#> V6 2.5 2.5 2.5

reprex package (v2.0.1)

于 2022-04-29 创建

附录

extract 的替代方法是 [:

matrix(1:30, ncol = 6) %>% as.data.frame() %>%
list(
    a = list(
        cor(.[,1:3]),
        cov(.[,1:3])
    ),
    b = list(
        cor(.[,4:6]),
        cov(.[,4:6])
    )
) %>%
  `[`(-1)

您可以将其通过管道传输到匿名函数中,以明确告诉 R 在构建输出列表时在哪里使用您的数据框:

library(tidyverse)

matrix(1:30, ncol = 6)  %>%  as.data.frame()  %>%
  (function(df) {
    list(a = list(cor(df[, 1:3]),
                  cov(df[, 1:3])),
         b = list(cor(df[, 4:6]),
                  cov(df[, 4:6])))
  })
#> $a
#> $a[[1]]
#>    V1 V2 V3
#> V1  1  1  1
#> V2  1  1  1
#> V3  1  1  1
#> 
#> $a[[2]]
#>     V1  V2  V3
#> V1 2.5 2.5 2.5
#> V2 2.5 2.5 2.5
#> V3 2.5 2.5 2.5
#> 
#> 
#> $b
#> $b[[1]]
#>    V4 V5 V6
#> V4  1  1  1
#> V5  1  1  1
#> V6  1  1  1
#> 
#> $b[[2]]
#>     V4  V5  V6
#> V4 2.5 2.5 2.5
#> V5 2.5 2.5 2.5
#> V6 2.5 2.5 2.5

这可能是 magrittr 管道的局限之一(据我所知)似乎无法告诉它不要将 LHS 作为第一个参数传递 - 除非大概是在其他地方明确用于相同级别的功能(如 lm 示例中)?与迁移到新管道 (|>) 一样令系统震惊,也许它添加的元素将来会解决这个问题。

reprex package (v2.0.1)

于 2022-04-29 创建

所以,在我发帖之后,我意识到我并没有真正考虑过检查是否还有其他可能有效的运算符。根据 magrittr's introduction page““exposition”管道,%$% 将 left-hand 侧对象中的名称暴露给 right-hand 侧表达式。” 似乎不一定是为了这个目的,但我用 %$% 替换了 %>%,现在它起作用了! (我仍然不知道使用 %$% 的潜在缺点,因此欢迎对此发表任何评论。)

library(magrittr)

matrix(1:16, ncol = 4) %>% as.data.frame() %$%
list(
    a = list(
        cor(.[,1:2]),
        cov(.[,1:2])
    ),
    b = list(
        cor(.[,3:4]),
        cov(.[,3:4])
    )
)

# $a
#     A matrix: 2 × 2 of type dbl
#     V1    V2
#     V1    1   1
#     V2    1   1

#     A matrix: 2 × 2 of type dbl
#     V1    V2
#     V1    1.666667    1.666667
#     V2    1.666667    1.666667

# $b
#     A matrix: 2 × 2 of type dbl
#     V3    V4
#     V3    1   1
#     V4    1   1

#     A matrix: 2 × 2 of type dbl
#     V3    V4
#     V3    1.666667    1.666667
#     V4    1.666667    1.666667