求助:使用sapply函数结合ifelse条件实现特定数据清洗需求
问题:清洗含连字符的字符串并补零
我是apply函数的新手,需要处理数据集df的x列,规则如下:
- 若x列的值包含连字符,将连字符前的字符串补零至5位,连字符后的字符串补零至4位
- 若字符串无连字符,则设为NA
我已经在df中添加了预期结果列,但尝试的两段代码都没成功:
第一段尝试的代码:
df=data.frame(x=c("55555555","4444-444","NULL","hello","0065440006123","22-111"))%>% mutate(nchar=nchar(x), detect=str_detect(x,"-"), xlcean=c(NA,"04444-0444",NA,NA,NA,"00022-0111")) df%>%mutate(xclean=sapply(strsplit(x,"-"), function(x) {ifelse(detect==T, paste(sprintf("%05d",as.numeric(x[1])), sprintf("%04d",as.numeric(x[2])), sep="-"),NA)}))
第二段尝试的代码:
df%>%mutate(x_clean= if (detect==T) {sapply(strsplit(x,"-"), function(x)paste(sprintf("%05d",as.numeric(x[1])), sprintf("%04d",as.numeric(x[2])), sep="-"))} else {NA})
解决方案
问题原因分析
- 第一段代码里,在
sapply的匿名函数中引用detect是整个列的逻辑向量,不是当前行的判断,导致无法逐行处理;同时,对不含连字符的字符串用strsplit会得到长度为1的列表,访问x[2]会引发错误。 - 第二段代码使用了
if而非if_else,if只能处理单个逻辑值,无法对整个向量的每行进行判断。
正确代码示例
方法一:用case_when结合str_replace
library(dplyr) library(stringr) # 初始化数据集 df <- data.frame(x=c("55555555","4444-444","NULL","hello","0065440006123","22-111")) %>% mutate( x_clean_expected = c(NA,"04444-0444",NA,NA,NA,"00022-0111") # 预期结果列 ) # 处理x列 df <- df %>% mutate( x_clean = case_when( # 匹配含连字符的行,捕获前后部分并补零 str_detect(x, "-") ~ str_replace(x, "(.*)-(.*)", function(match) { sprintf("%05d-%04d", as.numeric(match[2]), as.numeric(match[3])) }), # 其他情况设为NA TRUE ~ NA_character_ ) ) print(df)
方法二:用str_split结合sapply逐行处理
df <- df %>% mutate( x_clean = ifelse( str_detect(x, "-"), sapply(str_split(x, "-"), function(parts) { # 确保分割后有两个部分,避免报错 if(length(parts) == 2) { sprintf("%05d-%04d", as.numeric(parts[1]), as.numeric(parts[2])) } else { NA_character_ } }), NA_character_ ) )
运行后x_clean列会和预期结果一致。
内容的提问来源于stack exchange,提问作者Ashti
相关产品推荐
相关产品推荐

