在R中移除仅gene_ID列不同的重复行,保留首行
搞定仅gene_ID列有差异的重复行保留问题
问题说明
我手头有个大型数据集,里面好多行只有gene_ID列末尾不一样,其他列全相同,这导致直接用dplyr的duplicated()或者unique()没法处理。示例数据如下:
| gene_ID | Gene_Identifier | Category | Length |
|---|---|---|---|
| Wdfy1_chr1_79702262_79776143(-)_transcript=ENSMUST00000113515.7 | Wdfy1 | Spliced | 4551 |
| Wdfy1_chr1_79702262_79776143(-)_transcript=ENSMUST00000113514.7 | Wdfy1 | Spliced | 4551 |
| Wdfy1_chr1_79702262_79776143(-)_transcript=ENSMUST00000113513.7 | Wdfy1 | Spliced | 4551 |
| Wdfy1_chr1_79702262_79776143(-)_transcript=ENSMUST00000113512.7 | Wdfy1 | Spliced | 4551 |
我想把重复行都删掉,每组只留第一行。试了几个代码都不行:
- 用
aggregate:
test <- aggregate(gene_ID ~ ., df, toString)
合并出来的行数比预期多太多(本来要50行结果出了4000行),正逐行核对是不是符合需求。
- dplyr分组过滤:
test2 <- df %>% group_by_at(vars(-gene_ID)) %>% filter(n() > 1)
结果重复行全没了,啥也没保留。
- 分组加
duplicated:
test3 <- df %>% group_by_at(vars(-gene_ID)) %>% duplicated(df)
直接报错:Error: argument 'incomparables != FALSE' is not used (yet)。
解决办法
办法1:dplyr分组后取每组第一行
核心就是按除了gene_ID之外的所有列分组,然后挑每组的第一行:
library(dplyr) result <- df %>% group_by_at(vars(-gene_ID)) %>% slice(1) %>% # 留每组第一行 ungroup() # 取消分组变回普通数据框
办法2:用基础R的duplicated指定判断重复的列
直接用duplicated,告诉它只看除gene_ID外的列来判断重复,然后筛选非重复的行(每组自然留第一行):
# 先拿到除gene_ID外的所有列名 non_id_cols <- setdiff(colnames(df), "gene_ID") # 筛选出不重复的行 result <- df[!duplicated(df[non_id_cols]), ]
办法3:如果gene_ID前缀有规律,提取前缀后去重
要是gene_ID的前缀(比如例子里的Wdfy1_chr1_79702262_79776143(-))和其他列一一对应,也可以先提取前缀,再按前缀和其他列分组留第一行:
library(dplyr) library(stringr) result <- df %>% # 提取_transcript=之前的部分当前缀 mutate(gene_prefix = str_extract(gene_ID, "^.*(?=_transcript=)")) %>% group_by(gene_prefix, Gene_Identifier, Category, Length) %>% slice(1) %>% select(-gene_prefix) %>% # 删掉临时加的前缀列 ungroup()
为啥之前的代码不行?
aggregate是把每组的gene_ID拼成字符串,所以行数是去重后的组数,但你要的是保留原行结构,不是合并ID,所以不符合需求。filter(n() > 1)只会留下那些有重复的组,但会把组里所有行都留下,不是只留第一行,逻辑错了。- 分组后直接用
duplicated(df)是用法错误,分组后的数据结构变了,duplicated不能这么用,得用分组内的筛选函数比如slice或者filter(row_number() == 1)。
内容的提问来源于stack exchange,提问作者ispeakcat
相关产品推荐
相关产品推荐

