我想创建一个数据框架的关联和协方差矩阵列表。我尝试使用magritr管道操作符(%>%
)将数据框输送到列表中,如下面的示例所示。问题是数据框本身作为第一个列表元素被插入。我知道管道操作符的默认行为是将对象注入到它被管道插入的函数的第一个位置。然而,我很想知道是否有一种简单的方法来管道矩阵/数据框到一个列表中的函数,同时避免数据框本身的插入?
代码示例:
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
所以,在我发布之后,我意识到我没有真正考虑检查是否有其他可能工作的操作符。根据magrittr
的介绍页面,"说明"管道,%$%
将左侧对象中的名称暴露给右侧表达式。">似乎并不一定是为了这个目的,但我用%$%
代替了%>%
,现在它工作了!(我仍然不知道使用%$%
的潜在缺点,所以对此的任何评论都是赞赏的。)
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
只需将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包(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包(v2.0.1)于2022-04-29创建