如何在readr中用tidy选择语法批量指定多列类型?
解决方案:批量指定列类型(支持tidy-select语法)
readr本身并未内置类似dplyr::across()的语法直接在cols()中使用,但可以通过两种方式实现你的需求:
一、使用vroom包(tidyverse官方替代,原生支持)
{vroom}是readr的高性能替代包,它的vroom()函数允许在col_types参数中直接使用tidy-select选择器,完美匹配你想要的写法:
library(vroom) # 自定义因子级别 custom_levels <- c("low", "medium", "high") # 读取文件,批量指定列类型 vroom("your_file.csv", col_types = list( starts_with("Col") = col_integer(), starts_with("Var") = col_character(), contains("Date") = col_date(format = "%m-%d-%Y"), Fct1:Fct9 = col_factor(levels = custom_levels) ), guess_max = 5 )
这种方式无需额外封装,直接支持你需要的所有场景:按列名前缀、关键词匹配、列范围指定,且可以使用完整的col_xxx()函数(带参数)。
二、基于readr+tidyselect+purrr手动实现
如果必须使用readr,可以通过tidyselect筛选列名,结合purrr生成列类型规范:
步骤1:先获取文件的列名(不解析数据)
library(readr) library(tidyselect) library(purrr) # 读取列名 col_names <- read_csv("your_file.csv", n_max = 0) %>% names()
步骤2:生成列类型规范
custom_levels <- c("low", "medium", "high") col_spec <- cols( # 批量指定前缀为Col的列为整数 !!!set_names( map(starts_with("Col", vars = col_names), ~col_integer()), starts_with("Col", vars = col_names) ), # 批量指定前缀为Var的列为字符 !!!set_names( map(starts_with("Var", vars = col_names), ~col_character()), starts_with("Var", vars = col_names) ), # 批量指定包含Date的列为日期(自定义格式) !!!set_names( map(contains("Date", vars = col_names), ~col_date(format = "%m-%d-%Y")), contains("Date", vars = col_names) ), # 批量指定Fct1到Fct9为因子(自定义级别) !!!set_names( map(all_of(paste0("Fct", 1:9)), ~col_factor(levels = custom_levels)), paste0("Fct", 1:9) ) )
步骤3:读取文件
read_csv("your_file.csv", col_types = col_spec, guess_max = 5)
可选:封装成复用函数
如果需要多次使用,可以封装一个函数简化操作:
make_readr_col_spec <- function(col_names, ...) { args <- rlang::enquos(...) spec_list <- list() for (arg in args) { selector <- rlang::f_lhs(arg) col_fun <- rlang::f_rhs(arg) selected_cols <- eval_select(selector, tibble::tibble(!!!set_names(col_names, col_names))) spec_list[names(selected_cols)] <- map(names(selected_cols), ~rlang::eval_tidy(col_fun)) } do.call(cols, spec_list) } # 使用示例 col_spec <- make_readr_col_spec(col_names, starts_with("Col") ~ col_integer(), starts_with("Var") ~ col_character(), contains("Date") ~ col_date(format = "%m-%d-%Y"), Fct1:Fct9 ~ col_factor(levels = custom_levels) )
内容的提问来源于stack exchange,提问作者user18894435
相关产品推荐
相关产品推荐

