如何基于映射表动态转换任意列名的tibble数据类型?
如何基于列名-数据类型映射表动态转换tibble的列类型?
问题背景
我需要将多份CSV文件合并为tibble,但每次运行时文件的列名都不固定。之前用mutate_at()手动设置数据类型,列名变化时就得修改函数,效率很低。现在有一份列名与数据类型的映射表columns,以及待处理的tibbledf,想通过映射表自动为df的列分配对应数据类型。
映射表和待处理数据如下:
columns <- tribble( ~.colname, ~.datatype, "start_date", "date", "stop_date", "date", "order_num", "character", "rate", "currency", "amount", "integer" ) df <- tribble( ~start_date, ~stop_date, ~order_num, ~rate, ~amount, "2023-06-01", "2023-06-30", "52471", "1.25", "20" )
(注:原df列名的前缀.应为笔误,已修正为与映射表匹配的列名)
解决方案
可以通过自定义类型转换函数,结合dplyr或purrr的工具实现动态转换,无需手动指定列名:
步骤1:定义类型转换函数
先写一个根据类型字符串返回对应转换逻辑的函数,覆盖你需要的所有数据类型:
convert_type <- function(x, type) { switch( type, date = as.Date(x), character = as.character(x), currency = as.numeric(x), # 若货币值带$符号,可改为`as.numeric(sub("^\\$", "", x))` integer = as.integer(x), x # 默认返回原数据,处理未匹配的类型 ) }
步骤2:基于映射表动态转换列类型
方法1:使用dplyr::across
利用across()结合映射表,自动匹配列名对应的类型:
library(dplyr) df_processed <- df %>% mutate( across( all_of(columns$.colname), ~ convert_type(., columns$.datatype[match(cur_column(), columns$.colname)]) ) )
方法2:使用purrr::map2_df
通过map2_df()同时遍历df的列和对应的类型,批量转换:
library(purrr) library(dplyr) # 匹配每一列对应的类型 matched_types <- columns$.datatype[match(names(df), columns$.colname)] # 批量转换并返回tibble df_processed <- map2_df(df, matched_types, convert_type)
验证结果
运行后查看转换后的列类型:
str(df_processed)
输出会显示各列已转换为映射表指定的类型:
tibble [1 × 5] (S3: tbl_df/tbl/data.frame) $ start_date: Date, format: "2023-06-01" $ stop_date : Date, format: "2023-06-30" $ order_num : chr "52471" $ rate : num 1.25 $ amount : int 20
内容的提问来源于stack exchange,提问作者Charles Knell
相关产品推荐
相关产品推荐

