如何像vroom那样用字符串批量转换已有tibble的列类型?
批量按指定字符串转换tibble列类型的实现方法
问题描述
现有一个6列的tibble数据,结构如下:
d <- structure(list(a = c(9, 9, 9, 9, 9, 9, 9), b = structure(c(2018, 2018, 2018, 2018, 2018, 2018, 2018), class = "yearmon"), c = c("605417CA", "605417CB", "606822AS", "606822AT", "606822AU", "606822AV", "60683MAB"), d = c(NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_), e = c(0, 0, 0, 0, 0, 0, 0), f = c(2772, 2772, 46367, 46367, 46367, 46367, 47601)), row.names = c(NA, -7L), class = c("tbl_df", "tbl", "data.frame"))
需要将各列类型依次转换为:factor、factor、factor、integer、integer、factor。如果是从外部文件读取数据,vroom(path, col_types = "fffiif")可以直接通过这个字符串完成类型转换,但当前数据是中间计算结果,不想通过存文件再读取的方式处理。
尝试过以下方法均无法满足需求:
mutate逐个转换变量太繁琐;- 转换规则不依赖列原有类型(比如a和e都是double类型,却要分别转成factor和integer),
mutate_if无法适用; - 找不到类似
set_colnames的批量设置列类型的函数; readr::type_convert仅支持character类型列的转换。
解决方案
可以结合readr的类型解析逻辑和purrr的批量映射来实现直接转换:
方法1:自定义类型映射批量转换
library(dplyr) library(purrr) # 建立类型字符到转换函数的映射 type_mapping <- list( f = as.factor, i = as.integer ) # 拆分类型字符串为单个类型标记 target_types <- strsplit("fffiif", "")[[1]] # 对每一列应用对应的转换函数 d_converted <- d %>% map2_dfr(.x = ., .y = target_types, ~ type_mapping[[.y]](.x)) # 检查转换后的结构 str(d_converted)
方法2:利用readr的cols_spec实现更贴近vroom的转换
如果需要完全对齐vroom的类型处理逻辑(比如解析NA的方式),可以借助readr的列规格对象:
library(dplyr) library(purrr) library(readr) # 将类型字符串转为cols_spec对象 col_spec <- as.cols_spec("fffiif") # 提取每一列对应的解析函数 parse_functions <- map(col_spec$cols, ~ .x$parse_fun) # 批量应用解析函数 d_converted <- d %>% map2_dfr(.x = ., .y = parse_functions, ~ .y(.x)) # 验证结果 str(d_converted)
说明:对于原本是yearmon类型的列b,转换为factor时会保留其格式化后的显示值,若需要自定义factor水平可单独调整。
内容的提问来源于stack exchange,提问作者FBr
相关产品推荐
相关产品推荐

