使用Tidyr Separate正则分割列:提取Y/N与额外信息
解决方案:拆分包含Y/N和注释的Surgery列
我明白你遇到的麻烦了——尝试用separate拆分Surgery列却没得到想要的结果,这是因为你的数据里有多种格式:纯Y/N、Y加连字符注释、还有完全没有Y/N的内容,默认的拆分规则没法覆盖所有情况。下面给你几个灵活的解决方案,都基于tidyverse工具实现:
首先先确认你的原始数据:
library(tidyverse) df <- data.frame(Names=c("Patient1","patient2","Patient3","Patient4","patient5"), Surgery=c("Y","N","Y-this kind of surgery","See note","Y"))
方法1:用str_extract和str_remove(最直观)
这个方法先提取开头的Y/N到新列,再移除Y/N和多余的连字符得到注释列,逻辑清晰容易调整:
df_processed <- df %>% mutate( # 提取开头的Y或N,没有则返回NA Surgery_YN = str_extract(Surgery, "^Y|^N"), # 移除开头的Y-、N-、Y、N,剩下的就是注释内容 Notes = str_remove(Surgery, "^Y-|^N-|^Y|^N"), # 把空字符串的Notes转为NA(对应纯Y/N的行) Notes = ifelse(Notes == "", NA, Notes) ) print(df_processed)
输出结果:
Names Surgery Surgery_YN Notes 1 Patient1 Y Y <NA> 2 patient2 N N <NA> 3 Patient3 Y-this kind of surgery Y this kind of surgery 4 Patient4 See note NA See note 5 patient5 Y Y <NA>
方法2:用separate配合正则分隔符
如果偏好使用separate,可以利用正则的正向后顾断言来匹配Y/N后面的连字符,再处理无Y/N的行:
df_processed <- df %>% separate(Surgery, into = c("Surgery_YN", "Notes"), # 只匹配Y或N后面的连字符作为分隔符 sep = "(?<=Y|N)-", # 没有注释的行填充NA fill = "right", # 多个分隔符时把剩余内容合并到Notes extra = "merge") %>% # 处理没有Y/N的行:把内容移到Notes,Surgery_YN设为NA mutate( Notes = case_when( !Surgery_YN %in% c("Y", "N") ~ Surgery_YN, TRUE ~ Notes ), Surgery_YN = ifelse(Surgery_YN %in% c("Y", "N"), Surgery_YN, NA) )
这个方法的输出和方法1完全一致。
方法3:用extract一次性匹配(最简洁)
extract可以通过正则表达式一次性捕获Y/N和注释内容,一步到位:
df_processed <- df %>% extract(Surgery, into = c("Surgery_YN", "Notes"), # 正则解释: # ^(Y|N)? 匹配开头可选的Y或N # (?:-(.*))? 可选的连字符加任意内容(非捕获组) regex = "^(Y|N)?(?:-(.*))?$", # 保留原Surgery列方便对比(可选,不需要可以去掉) remove = FALSE) %>% mutate( # 处理无Y/N的行:把原Surgery内容移到Notes,Surgery_YN设为NA Notes = ifelse(is.na(Surgery_YN), Surgery, Notes), Surgery_YN = ifelse(Surgery_YN %in% c("Y", "N"), Surgery_YN, NA) ) %>% # 移除原Surgery列(如果之前设置了remove=FALSE) select(-Surgery)
这个方法同样能得到符合需求的结果,适合喜欢简洁代码的场景。
内容的提问来源于stack exchange,提问作者Joe Crozier
相关产品推荐
相关产品推荐

