R 查找与某个值关联的子组,并使用每个ID对连续的子组进行计数

R 查找与某个值关联的子组,并使用每个ID对连续的子组进行计数,r,performance,data.table,R,Performance,Data.table,我请求您帮助设计一个非常有效的解决方案,以快速遍历14kk行表 基本上,问题包括为每个ID查找值==0的子组,并从他开始计算值==0的连续子组(每个ID内)的数量 这些新信息需要保存在一个由“ID”、“subgroup”和“Count”组成的外部表中 为了尽可能清楚,我将举一个例子。 假设我们有以下数据库: ID <- (1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3) subgroup <- c("1a1p", "

我请求您帮助设计一个非常有效的解决方案,以快速遍历14kk行表

基本上,问题包括为每个ID查找值==0的子组,并从他开始计算值==0的连续子组(每个ID内)的数量

这些新信息需要保存在一个由“ID”、“subgroup”和“Count”组成的外部表中

为了尽可能清楚,我将举一个例子。
假设我们有以下数据库:

ID <- (1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3)   
subgroup <- c("1a1p", "1a2p", "1a3p", "2a1p", "2a2p", "2a3p", "2a4p", "2a5p", "2a6p", "3a1p", "3a2p", "3a3p", "3a4p", "3a5p")
Value <- c(2000, 0, 0, 0, 0, 0, 0, 2000, 1800, 0, 0 , 0, 1750, 0)

df <- data.frame(ID, subgroup, Value)
请注意,
子组==“1a2p”
带有一个
计数==0
,这意味着它具有
值==0
的特征,但有0
子组
与他相邻,具有相同的
值==0

我真的希望我尽可能清楚


在以前版本的问题上,使用
system.info()
对性能进行测量,该问题只考虑功能
子组

数据表
方法

user: 881.21  system: 109.73  elapsed: 993.43  
user: 91.66  system: 0.56  elapsed: 93.05  
user: 1.67 system: 0.29  elapsed: 2.06

        
user: 75.28  system: 1.00  elapsed: 77.16
user: 104.75 system: 0.61  elapsed: 105.74
dplyr
进近

user: 881.21  system: 109.73  elapsed: 993.43  
user: 91.66  system: 0.56  elapsed: 93.05  
user: 1.67 system: 0.29  elapsed: 2.06

        
user: 75.28  system: 1.00  elapsed: 77.16
user: 104.75 system: 0.61  elapsed: 105.74
baser
进近

user: 881.21  system: 109.73  elapsed: 993.43  
user: 91.66  system: 0.56  elapsed: 93.05  
user: 1.67 system: 0.29  elapsed: 2.06

        
user: 75.28  system: 1.00  elapsed: 77.16
user: 104.75 system: 0.61  elapsed: 105.74

更新 更新任务的性能:

dplyr
进近

user: 881.21  system: 109.73  elapsed: 993.43  
user: 91.66  system: 0.56  elapsed: 93.05  
user: 1.67 system: 0.29  elapsed: 2.06

        
user: 75.28  system: 1.00  elapsed: 77.16
user: 104.75 system: 0.61  elapsed: 105.74
baser
进近

user: 881.21  system: 109.73  elapsed: 993.43  
user: 91.66  system: 0.56  elapsed: 93.05  
user: 1.67 system: 0.29  elapsed: 2.06

        
user: 75.28  system: 1.00  elapsed: 77.16
user: 104.75 system: 0.61  elapsed: 105.74

下面是一个使用
数据表的想法

library(data.table)

setDT(df)[, grp := rleid(Value == 0)][
           Value == 0, .(ID = first(ID), count = .N - 1), by = grp]
这就给了,


这里有一个使用
dplyr

library(dplyr)
df %>%
    mutate(grp = c(TRUE, diff(Value==0)>0)) %>% 
    filter(Value ==0) %>%
    group_by(grp = cumsum(grp)) %>%
    summarise(ID = first(ID), count = n()-1) %>%
    ungroup() %>% 
    select(-grp) 
# A tibble: 4 x 2
#    ID count
#  <fctr> <dbl>
#1   1a2p     0
#2   2a2p     2
#3   3a1p     2
#4   3a5p     0
更新 有了更新后的问题,我们可以进行分组

df %>% 
    mutate(grp = c(TRUE, diff(Value==0)>0)) %>%
    filter(Value == 0) %>%
    group_by(ID, grp = cumsum(grp)) %>%
    summarise(subgroup = first(subgroup), count = n()-1) %>% 
    ungroup() %>% 
    select(-grp)
# A tibble: 4 x 3
#    ID subgroup count
#  <dbl>   <fctr> <dbl>
#1     1     1a2p     1
#2     2     2a1p     3
#3     3     3a1p     2
#4     3     3a5p     0

你的例子出错了,我在手机上写的,现在已经修好了:)应该已经修好了,不是吗?谢谢:这张表是按ID排序的吗?或者ID 1a1p是否可以重新出现在第15行中,例如eaxmple?数据库的排序如我在问题中所示。ID是唯一的复合密钥。如果您需要更多信息,请成为我的客人:)谢谢!我很想做一个效率测试来发现这三种方法中哪一种是有效的faster@Enrico您可以在大数据集(即1e6或1e7)上使用
microbenchmark
,并检查哪个数据集更快。由于microbenchmark修改了输入数据,因此无法使用数据表,因此,'system.info()的结果'是用户:881.21系统:109.73经过时间:993.43。您使用microbenchmark的两种方法仍在运行,我稍后会更新您。@Enrico谢谢,您可以在您的帖子中进行更新。我仍然无法使用microbenchmark运行它,因为基本R解决方案需要运行一整晚,dplyr解决方案需要运行一整晚。你认为System.info()基准测试也可以吗?我意识到我没有正确地暴露问题,我添加了一个导致大问题的小更改。我试图找出如何修改您的代码,但它不工作。你的算法能适应更新后的问题吗?或者它需要一种不同的方法?等我重新上线后,我会看一看。