R 计算每组特定值的序列数

R 计算每组特定值的序列数,r,count,sequence,R,Count,Sequence,假设我有一个带有ID和变量的数据帧,其中的响应是ON或OFF。 我想计算每组“打开”的运行次数。我几乎做到了这一点,但意识到我的解决方案并没有在小组中的第一个或最后一个值上发挥作用,这取决于我是在尝试使用超前还是滞后 我已经搜索了这么多,可以找到类似的问题,但似乎没有完全匹配这一点 id <- c("a", "a", "a", "a", "a", "b", "b

假设我有一个带有ID和变量的数据帧,其中的响应是ON或OFF。 我想计算每组“打开”的运行次数。我几乎做到了这一点,但意识到我的解决方案并没有在小组中的第一个或最后一个值上发挥作用,这取决于我是在尝试使用超前还是滞后

我已经搜索了这么多,可以找到类似的问题,但似乎没有完全匹配这一点

id <- c("a", "a", "a", "a", "a", "b", "b", "b", "b", "b","c", "c","c","c","c","c","c","c" ) category <- c("ON", "OFF", "OFF", "ON", "ON", "ON", "OFF", "OFF", "ON", "ON", "OFF", "OFF","OFF","OFF","OFF", "ON", "ON","ON") dat<-data.frame(id, category) 非常感谢您的帮助。我的实际数据集是40000行,有120个id,在每个id中,类别可以从ON或OFF开始

输出如下:

# id    category       n    
# a:1   OFF:0    Min.   :1  
# b:1   ON :2    1st Qu.:1  
# c:0            Median :1  
#                Mean   :1  
#                3rd Qu.:1  
#                Max.   :1 

因此,解释为2个id在任何点上运行“ON”,并且运行ON的中位数(在这个小样本中)在
base-R
中为1

tapply(dat$category, dat$id, function(x) with(rle(as.character(x)),sum(values == "ON")))

a b c 
2 2 1 
#第一步 超出% 分组依据(id)%>% nest() #结果步骤1 出来 ##tibble:3 x 2 ##组:id[3] #id数据 # #1A #2 b #3 c #步骤2 超出% 变异(运行=映射(数据,~{ 出图% #该行用于筛选类别和运行的最小行 过滤器(类别==“打开”,长度>1)%>% 解组()%>% 变异_if(is.character,as_factor) 出来 ##tibble:3 x 3 #id长度类别 # #1 a 2开 #2b2on #3c3开 计数(out、id、category、sort=TRUE) ##tibble:3 x 3 #身份证类别n # #一对一 #2 b在1上 #3月1日c 摘要(外) #id长度类别 #a:1分钟:2.000开始:3 #b:1第一区:2.000 #c:1中位数:2.000 #平均数:2.333 #第三季度:2.500 #最多:3.000
我不太确定您想要的输出应该是什么,但可能类似于
rle(category)
(其中
rle()
base
函数)可能是你在寻找的汉克斯,我正在努力理解你的第二个答案,请原谅我的无知。第一个答案我想我理解了,但当我检查真实数据时,它似乎是重复计算的第一部分(直到评论)按数据中的id为您提供所有类别运行的列表。然后,您可以按类别(例如,仅“打开”类别)和运行长度(例如>1)筛选这些运行。希望这有帮助。噢,谢谢。由于它在示例数据上运行,我收到一个错误:rle中的错误(.x$category):“x”必须是原子类型的向量。我猜你没有得到它,所以不确定我为什么得到它?嗯……我刚刚用更多ID模拟了你的数据集,但没有错误。可能添加了
print(.x)
之前作为
map
命令的第一行,查看在哪个子集上出现错误以及该子集的外观。恐怕仍在努力解决这个问题,您是否完全按照编写的方式实现了?是否有任何方法可以使用dplyr解决方案实现这一点?
tapply(dat$category, dat$id, function(x) with(rle(as.character(x)),sum(values == "ON")))

a b c 
2 2 1 
# step 1 out <- dat %>% group_by(id) %>% nest() # outcome step 1 out # # A tibble: 3 x 2 # # Groups: id [3] # id data # <chr> <list> # 1 a <tibble [5 x 1]> # 2 b <tibble [5 x 1]> # 3 c <tibble [8 x 1]> # step 2 out <- out %>% mutate(run = map(data, ~ { out_map <- rle(.x$category) out_map <- tibble(length = out_map[[1]], category = out_map[[2]]) return(out_map) })) %>% select(-data) # outcome step 2 out # # A tibble: 3 x 2 # # Groups: id [3] # id run # <chr> <list> # 1 a <tibble [3 x 2]> # 2 b <tibble [3 x 2]> # 3 c <tibble [2 x 2]> # step 3 out <- out %>% unnest(cols = c(run)) %>% # this line lets you filter for category and the minimum line of the run filter(category == "ON", length > 1) %>% ungroup() %>% mutate_if(is.character, as_factor) out # # A tibble: 3 x 3 # id length category # <fct> <int> <fct> # 1 a 2 ON # 2 b 2 ON # 3 c 3 ON count(out, id, category, sort = TRUE) # # A tibble: 3 x 3 # id category n # <fct> <fct> <int> # 1 a ON 1 # 2 b ON 1 # 3 c ON 1 summary(out) # id length category # a:1 Min. :2.000 ON:3 # b:1 1st Qu.:2.000 # c:1 Median :2.000 # Mean :2.333 # 3rd Qu.:2.500 # Max. :3.000