如何为data.table中符合条件的计数组生成唯一标识ID
解决方案:为重叠区间关联的value生成唯一分组ID
针对你的需求,我们需要将**互相包含在彼此(min_val, max_val)区间内(或间接连通)**的value划分为同一组,并生成唯一id。下面提供两种可行方法:
方法1:使用igraph包识别连通分量(推荐,适用于所有情况)
这种方法通过图论中的连通分量概念,将每个value视为节点,若两个value互相处于对方的区间内则建立连接,最终同一连通分量的节点即为同一组。
library(data.table) library(igraph) # 修正原始数据的行名错误(原row.names=-4L应为-8L) dat <- setDT(structure(list(value = c(94.01, 94.02, 94.03, 95, 100, 100.1, 200, 200.1), min_val = c(94, 94, 94.01, 94.98, 99, 99.1, 199, 199), max_val = c(94.02, 94.03, 94.04, 95.02, 101, 101, 201, 201)), class = c("data.table", "data.frame"), row.names = c(NA, -8L))) # 计算count列(保留你的原始逻辑) dat[, count := mapply(function(mi,ma) sum(mi < value & value < ma), min_val, max_val)] # 构建邻接矩阵:判断每个value是否落在另一行的(min_val, max_val)区间内 adj_matrix <- outer(seq_len(nrow(dat)), seq_len(nrow(dat)), function(i,j) dat$min_val[i] < dat$value[j] & dat$value[j] < dat$max_val[i]) # 构建无向图并移除自环 graph_obj <- graph_from_adjacency_matrix(adj_matrix, mode = "undirected", diag = FALSE) # 为每行分配连通分量的ID dat[, id := components(graph_obj)$membership]
运行后,id列会输出:1,1,1,2,3,3,4,4,对应4个独立分组,符合预期。
方法2:无需额外包,通过排序+累积分组(适用于区间按value有序重叠的场景)
如果你的数据中,重叠区间的value是连续排序的,可以通过排序后判断区间重叠性来生成分组ID:
library(data.table) dat <- setDT(structure(list(value = c(94.01, 94.02, 94.03, 95, 100, 100.1, 200, 200.1), min_val = c(94, 94, 94.01, 94.98, 99, 99.1, 199, 199), max_val = c(94.02, 94.03, 94.04, 95.02, 101, 101, 201, 201)), class = c("data.table", "data.frame"), row.names = c(NA, -8L))) dat[, count := mapply(function(mi,ma) sum(mi < value & value < ma), min_val, max_val)] # 按value排序 sorted_dat <- dat[order(value)] # 生成分组ID:当当前行的min_val大于等于前一组的最大max_val时,新建分组 sorted_dat[, id := cumsum(min_val >= shift(cummax(max_val), fill = -Inf))] # 将ID合并回原数据(若不需要保持原始顺序可跳过此步) dat[sorted_dat, on = .(value), id := i.id]
关于你尝试的mean方法说明
你之前尝试用均值生成ID的思路存在误区:直接计算mean(value)会得到整个列的均值,而非组内均值。只有先完成分组,才能通过dat[, mean_val := mean(value), by = id]生成组内均值作为标识,但使用连通分量的整数ID更简洁高效。
内容的提问来源于stack exchange,提问作者iuliux
相关产品推荐
相关产品推荐

