如何在分组滑动窗口中按条件统计hr>0的出现次数?
分组滑动窗口统计hr>0的次数
示例数据集
structure(list(id = c("AA2A", "AA2A", "AA2A", "AA2A", "AA2A", "AA2A", "XX7H", "XX7H", "XX7H", "XX7H", "XX7H", "XX7H"), hr = c(31L, 31L, 31L, 0L, 0L, 50L, 50L, 0L, 0L, 0L, 0L, 84L)), class = "data.frame", row.names = c(NA, -12L))
需求
针对每个id,在大小为3的滑动窗口中统计hr>0的出现次数,生成新列result。
尝试过的无效代码
slider包
mutate(result = slide_dbl(hr,length(hr>0), .before = 3, .after = 0, .complete = FALSE)) mutate(result = slide_dbl(hr,summarise_if(hr>0), .before = 3, .after = 0, .complete = FALSE))
zoo包
mutate(result=rollapply(hr, width=3, FUN=function(x) length(hr>0), partial=TRUE, align='left'))
注:完整数据集含100万行、10列,zoo包代码运行过慢;此前用
slide_dbl计算均值、中位数正常,但添加hr>0条件后失效;分组操作group_by(id)无问题,工作环境为tidyverse。
解决方案
正确的slider包实现
核心问题是你在slide_dbl里传入的函数错误:应该针对**窗口内的子集x**计算,而不是引用整个列hr。同时要注意窗口参数的设置,确保窗口大小为3:
library(tidyverse) library(slider) df %>% group_by(id) %>% mutate( # 窗口为当前行 + 前2行,共3行;不足3行时仍计算(.complete=FALSE) result = slide_dbl(hr, ~sum(.x > 0), .before = 2, .complete = FALSE) # 如果需要窗口是当前行 + 后2行(对应zoo的align='left'),则用: # result = slide_dbl(hr, ~sum(.x > 0), .after = 2, .complete = FALSE) ) %>% ungroup()
代码解释
~sum(.x > 0):匿名函数,对每个滑动窗口内的hr值,统计大于0的数量(sum(逻辑值)等价于计数TRUE的个数,比length(which(.x>0))更高效)。.before = 2:表示窗口包含当前行及前面2行,总大小为3;如果你的需求是从当前行往后取3个(和zoo的align='left'一致),则改用.after = 2。slider包基于C++实现,性能远优于zoo的rollapply,适合百万级行的大数据集。
针对示例数据集的输出
运行上述代码后,示例数据的结果如下(以.before=2为例):
# A tibble: 12 × 3 id hr result <chr> <int> <int> 1 AA2A 31 1 2 AA2A 31 2 3 AA2A 31 3 4 AA2A 0 2 5 AA2A 0 1 6 AA2A 50 1 7 XX7H 50 1 8 XX7H 0 2 9 XX7H 0 1 10 XX7H 0 0 11 XX7H 0 0 12 XX7H 84 1
内容的提问来源于stack exchange,提问作者Bettina
相关产品推荐
相关产品推荐

