rlang - 获取作为字符串传递的对象的 class,而不是字符串本身或现状

rlang - get the class of an object passed as a string, rather than the string itself or the quo

我试图通过传递列名称的字符串来获取 tibble 中列的 classes。像往常一样,rlang 的文档是如此难以辨认,以至于我无法弄清楚如何使字符串被评估为实际对象,并且我已经尝试 return class of "quosure" 或 "name".

require(tidyverse)
#> Loading required package: tidyverse
suppressPackageStartupMessages(library(rlang))

(colstable <- mtcars %>% names %>% enframe(name = NULL, value = "column"))
#> # A tibble: 11 x 1
#>    column
#>    <chr> 
#>  1 mpg   
#>  2 cyl   
#>  3 disp  
#>  4 hp    
#>  5 drat  
#>  6 wt    
#>  7 qsec  
#>  8 vs    
#>  9 am    
#> 10 gear  
#> 11 carb


colstable %>% 
  mutate(colclass = class(sym(paste0("mtcars$", column))))
#> Error: Only strings can be converted to symbols


#This crashes Rstudio immediately:
#colstable %>% 
  #mutate(colclass = class(quo(paste0("mtcars$", column))))

class(sym("mtcars$mpg"))
#> [1] "name"

class(quo("mtcars$mpg"))
#> [1] "quosure" "formula"

#Desired output would be the classes as produced by str()
str(mtcars)
#> 'data.frame':    32 obs. of  11 variables:
#>  $ mpg : num  21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
#>  $ cyl : num  6 6 4 6 8 6 8 4 4 6 ...
#>  $ disp: num  160 160 108 258 360 ...
#>  $ hp  : num  110 110 93 110 175 105 245 62 95 123 ...
#>  $ drat: num  3.9 3.9 3.85 3.08 3.15 2.76 3.21 3.69 3.92 3.92 ...
#>  $ wt  : num  2.62 2.88 2.32 3.21 3.44 ...
#>  $ qsec: num  16.5 17 18.6 19.4 17 ...
#>  $ vs  : num  0 0 1 1 0 1 0 1 1 1 ...
#>  $ am  : num  1 1 1 0 0 0 0 0 0 0 ...
#>  $ gear: num  4 4 4 3 3 3 3 4 4 4 ...
#>  $ carb: num  4 4 1 1 2 1 4 2 2 4 ...

#Ie, all the values of "colclass" should be "num"

reprex package (v0.3.0)

于 2020-04-15 创建

发生错误是因为 sym 仅适用于单个元素。在这里,我们需要 syms (但这不是获得预期输出的路线)。带有变量名的 $ 将按字面意思计算它,因此请改用 [[

如果我们需要 class,那么只需要

library(dplyr)
colstable %>%
      rowwise %>% 
      mutate(colclass = class(mtcars[[column]]) )
# A tibble: 11 x 2
# Rowwise: 
#   column colclass
#   <chr>  <chr>   
# 1 mpg    numeric 
# 2 cyl    numeric 
# 3 disp   numeric 
# 4 hp     numeric 
# 5 drat   numeric 
# 6 wt     numeric 
# 7 qsec   numeric 
# 8 vs     numeric 
# 9 am     numeric 
#10 gear   numeric 
#11 carb   numeric 

map

library(purrr)
colstable %>%
     mutate(colclass = map_chr(column ~ class(mtcars[[.x]])))

或者如果我们需要eval计算表达式

library(stringr)
colstable %>%
    mutate(colclass = map_chr(rlang::parse_exprs(str_c("mtcars$", column, collapse=";")),
         ~ class(rlang::eval_tidy(.x))))
# A tibble: 11 x 2
#   column colclass
#   <chr>  <chr>   
# 1 mpg    numeric 
# 2 cyl    numeric 
# 3 disp   numeric 
# 4 hp     numeric 
# 5 drat   numeric 
# 6 wt     numeric 
# 7 qsec   numeric 
# 8 vs     numeric 
# 9 am     numeric 
#10 gear   numeric 
#11 carb   numeric 

这里真的没有必要 rlang 或任何非标准评估。

我们可以使用 map 获取 class 列,并获取长格式数据。

library(tidyverse)
map_df(mtcars, class) %>% pivot_longer(cols = everything())

#  column class  
#   <chr>  <chr>  
# 1 mpg    numeric
# 2 cyl    numeric
# 3 disp   numeric
# 4 hp     numeric
# 5 drat   numeric
# 6 wt     numeric
# 7 qsec   numeric
# 8 vs     numeric
# 9 am     numeric
#10 gear   numeric
#11 carb   numeric

如果只有我们感兴趣的特定列,我们可以在获取它们 class 之前 select 它们。


如果您必须使用 colstable,我们可以 pull 数据框中的列并获取其 class。

colstable %>% mutate(class = map_chr(column, ~mtcars %>% pull(.x) %>% class))