在R语言中为数据框创建分组累加计数的clump列
我有如下的R数据框:
DF <- structure(list(Gene = c("GeneA", "GeneB", "GeneC", "GeneD", "GeneE"), region = c("1:5914103-1:7245590","1:27403851-1:30161281","1:27403851-1:30161281","1:27403851-1:30161281","1:34800556-1:37548572")), .Names = c("Gene","region"), row.names = c(NA, 5L), class = "data.frame")
初始数据框输出如下:
DF
Gene region
1 GeneA 1:5914103-1:7245590
2 GeneB 1:27403851-1:30161281
3 GeneC 1:27403851-1:30161281
4 GeneD 1:27403851-1:30161281
5 GeneE 1:34800556-1:37548572
我想要添加一个新列clump,对region列的不同分组进行累加式分类编号——即第一个出现的region编号为1,第二个新出现的为2,以此类推,相同region的行共用同一个编号,最终得到这样的结果:
DF
Gene region clump
1 GeneA 1:5914103-1:7245590 1
2 GeneB 1:27403851-1:30161281 2
3 GeneC 1:27403851-1:30161281 2
4 GeneD 1:27403851-1:30161281 2
5 GeneE 1:34800556-1:37548572 3
我在Stack Overflow上搜了不少类似问题,但大多是统计组内行数或者组内唯一值,没找到这种单纯对分组进行递增编号的方法,麻烦大家帮忙解答!
解决方案
这里有几种简单的实现方式,适配不同的工作流:
1. Base R 方法
直接利用factor()的特性就能搞定:
DF$clump <- as.integer(factor(DF$region, levels = unique(DF$region)))
解释:unique(DF$region)会按照region在数据框中出现的顺序提取唯一值,作为因子的水平;as.integer()会把每个水平转换成对应的整数编号,正好符合你需要的累加式编号逻辑。
2. dplyr 方法(tidyverse 风格)
如果你习惯用tidyverse工具链,有两种直观的写法:
library(dplyr) # 方法一:用group_indices DF <- DF %>% mutate(clump = group_indices(., region)) # 方法二:用cur_group_id(dplyr 1.0.0及以上版本推荐) DF <- DF %>% group_by(region) %>% mutate(clump = cur_group_id()) %>% ungroup()
两种方法都能实现需求,cur_group_id()是较新版本dplyr推出的函数,语义更清晰。
3. data.table 方法
如果处理的是大数据集,data.table的效率会更高:
library(data.table) setDT(DF)[, clump := .GRP, by = region]
解释:.GRP是data.table内置的变量,会按照分组的出现顺序自动分配递增的整数编号。
验证一下,这三种方法都能得到你想要的结果:
print(DF) # Gene region clump # 1: GeneA 1:5914103-1:7245590 1 # 2: GeneB 1:27403851-1:30161281 2 # 3: GeneC 1:27403851-1:30161281 2 # 4: GeneD 1:27403851-1:30161281 2 # 5: GeneE 1:34800556-1:37548572 3
内容的提问来源于stack exchange,提问作者Lynsey

