与管道运算符和[选择器一起使用时,为什么colnames函数会生成小标题(而不是矢量)?
问题:为什么该colnames函数与管道操作符%>%和[选择器一起使用时会生成一个小标题?
示例:给定以下标题:
library(tidyverse)
x <- tribble(
~a, ~b,
1, 0,
0, 1
)
问题:当与管道运算符和[选择器一起使用时,colnames 函数会生成一个 tibbe :
x %>% colnames(.)[1]
#> # A tibble: 2 x 1
#> a
#> <dbl>
#> 1 NA
#> 2 NA
而我希望它生成一个向量,就好像没有使用管道运算符一样:
colnames(x)[1]
#> [1] "a"
回答
管道将左侧插入到右侧 main 函数的第一个参数中,在本例中为 [ 。那就是这三个是一样的:
x %>% colnames(.)[1]
x %>% `[`(colnames(.), 1)
x %>% `[`(., colnames(.), 1)
最后一个是相同的,因为如果主函数的参数之一是点,它不会插入左侧。
为了防止它插入点使用 {...}
x %>% { colnames(.)[1] }
或使用:
x %>% colnames %>% .[1]
或使用dplyr::first或 dplyr::slice_head(n = 1) 或 dplyr::nth(1)purrr::pull(1)或magrittr::extract(1)或head(1)
x %>% colnames %>% first
回答
因为%>%自动插入.作为右侧的第一个参数,除非.已经作为右侧的顶级参数使用。
你的右手边是colnames(.)[1]-而且.是不是一个顶级参数在这里。事实上,该表达式colnames(.)[1]完全等同于
`[`(colnames(.), 1)
所以这个表达式的顶级参数是colnames(.)and 1。也不是.。所以%>%将你的表情转换为
`[`(x, colnames(x), 1)
这又等于
x[colnames(x), 1]
而那个表达并没有真正的意义,并且恰好导致了你所观察到的。
为避免.自动插入,您可以将表达式包装成{…}akrun 所示。或者您可以将复合表达式拆分为其组成部分:
x %>% colnames() %>% `[`(1L)
THE END
二维码