使用separate_rows按逗号拆分数据框行时遇循环错误求助
问题分析与解决:separate_rows拆分多列时的长度不匹配错误
问题重现
原始DataFrame
temp = structure(list(pid = c("s1", "s1", "s1"), LEFT_GENE = c("PTPRO", "EPS8", "DPY19L2,AC084357.2,AC027667.1"), RIGHT_GENE = c("", "FOx,D", "DPY19L2P2,S100A11P1")), row.names = c(1L, 2L, 3L), class = "data.frame")
对应的表格:
| pid | LEFT_GENE | RIGHT_GENE |
|---|---|---|
| s1 | PTPRO | |
| s1 | EPS8 | FOx,D |
| s1 | DPY19L2,AC084357.2,AC027667.1 | DPY19L2P2,S100A11P1 |
需求
将每列中以逗号分隔的项拆分为新行,生成所有可能的组合(例如第三行需生成3×2=6个新行)。
错误代码与提示
执行以下代码时报错:
temp %>% separate_rows(LEFT_GENE:RIGHT_GENE, sep=",") %>% data.frame(stringsAsFactors = F)
错误信息:
Error in `fn()`: ! In row 3, can't recycle input of size 3 to size 2. Run `rlang::last_error()` to see where the error occurred.
正常情况(前两行)
仅处理前两行时代码正常运行:
temp[1:2, ] %>% separate_rows(LEFT_GENE:RIGHT_GENE, sep=",") %>% data.frame(stringsAsFactors = F)
输出结果:
| pid | LEFT_GENE | RIGHT_GENE |
|---|---|---|
| s1 | PTPRO | |
| s1 | EPS8 | FOx |
| s1 | EPS8 | D |
错误原因
separate_rows函数默认要求:同一行中被拆分的多列,拆分后的元素数量必须一致;若其中某一列拆分后长度为1,函数会自动循环该列元素以匹配其他列的长度(比如第二行LEFT_GENE拆分为1个元素,RIGHT_GENE拆分为2个,函数会重复LEFT_GENE的元素2次来配对)。
但第三行中:
- LEFT_GENE拆分后得到3个元素:
DPY19L2、AC084357.2、AC027667.1 - RIGHT_GENE拆分后得到2个元素:
DPY19L2P2、S100A11P1
两者长度均大于1且不相等,函数无法自动完成循环匹配,因此触发"无法循环利用输入"的错误。
解决方案
要生成所有列拆分后的笛卡尔积组合,可通过以下两种方式实现:
方法一:先拆分列为列表,再双重unnest
library(tidyverse) temp %>% rowwise() %>% mutate( LEFT_GENE = str_split(LEFT_GENE, ","), RIGHT_GENE = str_split(RIGHT_GENE, ",") ) %>% unnest(LEFT_GENE) %>% unnest(RIGHT_GENE) %>% mutate(across(c(LEFT_GENE, RIGHT_GENE), str_trim)) # 去除元素两侧可能的空格
方法二:分步拆分+分组处理
library(tidyverse) temp %>% separate_rows(LEFT_GENE, sep = ",") %>% mutate(LEFT_GENE = str_trim(LEFT_GENE)) %>% group_by(pid, LEFT_GENE) %>% separate_rows(RIGHT_GENE, sep = ",") %>% mutate(RIGHT_GENE = str_trim(RIGHT_GENE)) %>% ungroup()
两种方法最终都会得到第三行的6个组合,以及前两行的正确结果。
内容的提问来源于stack exchange,提问作者Ahdee
相关产品推荐
相关产品推荐

