在R中如何原地mutate列同时保持列数据类型不变
问题说明
当数据框的indicator_col列为空值(NA)时,将以col_1_开头的多列置空,执行mutate操作后,被修改列的数据类型全部变为字符型,丢失了初始的数值、布尔、因子等类型。
初始数据data1包含以下类型的列:
col_1_ferment:数值型col_1_crutch:字符型col_1_grease:布尔型col_1_pump:因子型indicator_col:数值型(含NA值)
执行操作后得到的data2中,所有col_1_开头的列都变成了字符型,不符合预期。
复现代码
options(stringsasfactors = FALSE) col_1_ferment <- c(452,768,856,192,905,752) #numeric type col_1_crutch <- c('15','34','56','49','28','37') #character type col_1_grease <- c(TRUE,TRUE,FALSE,FALSE,TRUE,FALSE) #boolean type col_1_pump <- as.factor(c("3","6","3","2","1","2")) #factor type indicator_col <- c(2,NA,2,1,1,2) #numeric type data1 <- data.frame(col_1_ferment, col_1_crutch, col_1_grease, col_1_pump, indicator_col, check.rows = TRUE) # 导致类型改变的操作 data2 <- data1 %>% mutate(dplyr::across(starts_with("col_1_"), ~ ifelse(is.na(indicator_col), "", .x)))
解决方案
问题根源
ifelse函数会强制统一输出结果的类型,当用字符型的""作为NA行的替换值时,所有列都会被强制转换成字符型,从而丢失原有类型。
方法1:按列类型匹配对应空值(推荐)
针对不同数据类型的列,使用对应类型的空值替换,避免强制类型转换:
library(dplyr) data2_fixed <- data1 %>% mutate(across(starts_with("col_1_"), ~ case_when( is.na(indicator_col) ~ { # 根据列类型返回对应空值 if (is.numeric(.x)) NA_real_ else if (is.logical(.x)) NA else if (is.factor(.x)) as.factor(NA) else "" # 字符型保留空字符串 }, TRUE ~ .x # 非NA行保留原值 ))) # 验证列类型是否保留 sapply(data2_fixed, class)
方法2:先保存列类型,修改后恢复
如果需要统一处理后再恢复类型,可以先保存目标列的原始类型,修改完成后再逐个转换回去:
library(dplyr) # 1. 保存col_1_开头列的原始类型 target_cols <- starts_with("col_1_")(colnames(data1)) col_types <- sapply(data1[target_cols], class) # 2. 执行修改(先用NA统一替换,避免强制转字符) data2_temp <- data1 %>% mutate(across(target_cols, ~ ifelse(is.na(indicator_col), NA, .x))) # 3. 恢复各列的原始类型 data2_fixed <- data2_temp for (col in names(col_types)) { switch(col_types[col], numeric = data2_fixed[[col]] <- as.numeric(data2_fixed[[col]]), logical = data2_fixed[[col]] <- as.logical(data2_fixed[[col]]), factor = data2_fixed[[col]] <- as.factor(data2_fixed[[col]]), character = { # 字符型单独替换为空字符串 data2_fixed[[col]] <- ifelse(is.na(data2_fixed$indicator_col), "", data2_fixed[[col]]) } ) } # 验证类型 sapply(data2_fixed, class)
内容的提问来源于stack exchange,提问作者seehorse
相关产品推荐
相关产品推荐

