如何按500区间统计R dataframe中'si'的数量?
按固定区间统计DataFrame中"si"的数量
原始数据与需求
你有如下结构的DataFrame:
df <- data.frame(chr = c("chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1","chr1"), start = c(100,300,500,700,900,1100,1300,1500,1900,2100), end = c(200,400,600,800,1000,1200,1400,1600,1800,2000), sv = c("si", "si", "si", "si","si", "si","si", "si","si", "si"))
需求是按每500的区间(0-500、501-1001、1002-1502、1503-2003……)统计其中"si"的数量。
原函数的问题
你写的函数有三个核心问题:
- 变量名冲突:函数参数
start、end和DataFrame的列名重名,导致条件判断start >= start & end <= end逻辑混乱,R会优先调用函数参数的向量而非逐行的列值。 - 未使用筛选后的结果:
subset操作后没有赋值给变量,直接调用table(df$sv)时用的还是原始DataFrame,所以返回总数量。 - 未遍历区间:没有循环处理所有区间,仅执行了一次筛选统计,无法得到每个区间的结果。
解决方案
方法1:基础R循环遍历区间
先修改区间变量名避免冲突,再逐个区间筛选统计:
# 定义区间起止(修改变量名避免冲突) start_intervals <- c(1,501,1002,1503) end_intervals <- c(500, 1001, 1502, 2003) # 初始化结果容器 si_counts <- numeric(length(start_intervals)) # 遍历每个区间统计 for (i in seq_along(start_intervals)) { # 筛选当前区间内的行:df的start >= 区间start,且df的end <= 区间end filtered_rows <- subset(df, start >= start_intervals[i] & end <= end_intervals[i]) # 统计si数量(如果有其他sv类型,改用sum(filtered_rows$sv == "si")) si_counts[i] <- nrow(filtered_rows) } # 给结果添加区间名称 names(si_counts) <- paste(start_intervals, end_intervals, sep = "-") si_counts
运行后得到结果:
1-500 501-1001 1002-1502 1503-2003 2 3 2 2
方法2:用cut函数快速分组统计
如果区间规则固定,用cut函数给数据分组后直接统计,更简洁:
# 定义区间断点,覆盖所有数据范围 breaks <- c(0, 500, 1001, 1502, 2003, Inf) # 给df添加区间分组列(right=FALSE表示左闭右开区间,可根据需求调整) df$interval <- cut(df$end, breaks = breaks, right = FALSE) # 统计每个区间的si数量 table(df$interval)
运行结果:
[0,500) [500,1001) [1001,1502) [1502,2003) [2003, Inf) 2 3 2 2 1
(注:最后一个区间[2003, Inf)对应df中start=2100、end=2000的行,因end=2000小于2003,实际不会被统计到,这里是断点设置的延伸,可根据需求调整断点)
内容的提问来源于stack exchange,提问作者marduk
相关产品推荐
相关产品推荐

