如何将数据框中bm_id列按前3个字符拆分为两列?
拆分bm_id列:提取前3个字符到species列,剩余字符放入id列
问题场景
现有如下数据集,需要将bm_id列的前3个字符拆分至单独的species列,剩余字符放入id列:
| bm_id | |
|---|---|
| 1 | popCL20TE |
| 2 | agrST20 |
| 3 | agrST20-09SE |
尝试了以下两段代码,未成功实现拆分,还生成了多余空列:
尝试的代码1
bm_id[c('species', 'id')] <- tstrsplit(bm_id$bm_id, '(?<=.{3})', perl = TRUE)
尝试的代码2
bm_id2 <- tidyr::separate(bm_id, bm_id, into = c("species", "id"), sep = 3)
正确解决方案
方法1:修正tidyr::separate用法
你之前的separate逻辑基本正确,核心问题是数据框名和列名重名(都叫bm_id)导致解析混乱。建议给数据框起一个和列名不同的名字(比如df),再执行拆分:
library(tidyr) # 假设你的数据框实际名为df df <- df %>% separate(bm_id, into = c("species", "id"), sep = 3, remove = FALSE)
sep = 3:指定在第3个字符后拆分,刚好把前3位分到species,剩余内容分到idremove = FALSE:可选参数,保留原bm_id列;不需要原列可直接删除该参数
方法2:使用data.table::tstrsplit
如果用data.table工具,同样要避免数据框名和列名重名:
library(data.table) setDT(df) df[, c("species", "id") := tstrsplit(bm_id, '(?<=.{3})', perl = TRUE)]
正则表达式(?<=.{3})是正向断言,含义是在3个任意字符之后的位置拆分,逻辑本身没问题,之前失败大概率是数据框名与列名冲突导致的引用错误。
方法3:基础R原生实现
不需要额外依赖包的话,直接用字符串截取函数更直观:
df$species <- substr(df$bm_id, 1, 3) df$id <- substr(df$bm_id, 4, nchar(df$bm_id))
substr(df$bm_id, 1, 3):提取bm_id的第1到第3个字符substr(df$bm_id, 4, nchar(df$bm_id)):提取从第4个字符到结尾的全部内容
失败原因分析
最可能的问题是你将数据框命名为bm_id,和目标列名完全重名,导致R无法正确区分数据框和列的引用,进而出现赋值异常、拆分失效的情况。
内容的提问来源于stack exchange,提问作者Jane
相关产品推荐
相关产品推荐

