停止 tidyverse 在 lapply 中重命名列

问题描述 投票:0回答:2

当我在

group_by(col)
内使用
lapply()
时,列
a
b
被重命名为
get(col)
。我该如何阻止这种情况发生?我想在新对象中保留原始列名称。

MRE

输入

df <- data.frame(a = c(1, 1, 1), b = c(1, 1, 1), c = c(1, 1, 1))

lapply(c("a", "b"), function(col) {
  
  assign(col, df %>% group_by(get(col)) %>% summarize(), env = .GlobalEnv)
  
})

输出

[[1]]
# A tibble: 1 × 1
  `get(col)`
       <dbl>
1          1

[[2]]
# A tibble: 1 × 1
  `get(col)`
       <dbl>
1          1

如果有人解释“为什么”会发生这种重命名,以及如何阻止它,那就太好了。预先感谢。

r dplyr tidyverse lapply data-cleaning
2个回答
0
投票
group_by_at

代替:

lapply(c("a", "b"), function(col) {
  
  assign(col, df %>% group_by_at(col) %>% summarize(), env = .GlobalEnv)
  
})

[[1]]
# A tibble: 1 × 1
      a
  <dbl>
1     1

[[2]]
# A tibble: 1 × 1
      b
  <dbl>
1     1


                

0
投票
get

中使用

group_by
。这与非标准评估效果不佳。不过有几种选择。
你可以使用

!!ensym(col)

:

lapply(c("a", "b"), function(col) {
  assign(col, df %>% group_by(!!ensym(col)) %>% summarize(), env = .GlobalEnv)
})

类似的方法是
!!str2lang(col)

lapply(c("a", "b"), function(col) {
  assign(col, df %>% group_by(!!str2lang(col)) %>% summarize(), env = .GlobalEnv)
})

不过,推荐的方法似乎是使用
pick(all_of(col))

lapply(c("a", "b"), function(col) {
  assign(col, df %>% group_by(pick(all_of(col))) %>% summarize(), 
         env = .GlobalEnv)
})

across(all_of(col))

lapply(c("a", "b"), function(col) {
  assign(col, df %>% group_by(across(all_of(col))) %>% summarize(), 
         env = .GlobalEnv)
})

group_by_at

函数非常适合这种情况,但已被取代并且可能很快就会被弃用。无论如何,所有这些都会导致:

a
#> # A tibble: 1 x 1
#>       a
#>   <dbl>
#> 1     1

b
#> # A tibble: 1 x 1
#>       b
#>   <dbl>
#> 1     1

请注意,以这种方式将 
assign

变量添加到全局工作区被认为是不好的做法。将结果保存在列表中几乎总是更好:

dfs <- lapply(c("a", "b"), function(col) {
  df %>% group_by(across(all_of(col))) %>% summarize()
  }) |>
  setNames(c("a", "b"))

dfs
#> $a
#> # A tibble: 1 x 1
#>       a
#>   <dbl>
#> 1     1
#> 
#> $b
#> # A tibble: 1 x 1
#>       b
#>   <dbl>
#> 1     1

创建于 2023-09-14,使用 

reprex v2.0.2

© www.soinside.com 2019 - 2024. All rights reserved.