对r中的行进行分组、比较和计数

对r中的行进行分组、比较和计数,r,grouping,counting,R,Grouping,Counting,我有一个如下所示的数据框: system Id initial final 665 9 16001 6070 6071 683 10 16001 6100 6101 696 11 16001 6101 6113 712 10 16971 6150 6151 715 11 16971 6151 6163 4966 7 4118 10238 10242 5031 9

我有一个如下所示的数据框:

     system    Id initial final
665       9 16001    6070  6071
683      10 16001    6100  6101
696      11 16001    6101  6113
712      10 16971    6150  6151
715      11 16971    6151  6163
4966      7  4118   10238 10242
5031      9  4118   10260 10278
5088     10  4118   10279 10304
5115     11  4118   10305 10317


structure(list(system = c(9L, 10L, 11L, 10L, 11L, 7L, 9L, 10L, 
11L), Id = c(16001L, 16001L, 16001L, 16971L, 16971L, 4118L, 4118L, 
4118L, 4118L), initial = c(6070, 6100, 6101, 6150, 6151, 10238, 
10260, 10279, 10305), final = c(6071, 6101, 6113, 6151, 6163, 
10242, 10278, 10304, 10317)), .Names = c("system", "Id", "initial", 
"final"), row.names = c(665L, 683L, 696L, 712L, 715L, 4966L, 
5031L, 5088L, 5115L), class = "data.frame")
我想用下一个结构得到一个新的数据帧

     Id  system length initial final
1 16001 9,10,11      3    6070  6113
2 16971   10,11      2    6150  6163
3  4118       7      1   10238 10242
4  4118 9,10,11      3   10260 10317


structure(list(Id = c(16001L, 16971L, 4118L, 4118L), system =     structure(c(3L, 
1L, 2L, 3L), .Label = c("10,11", "7", "9,10,11"), class =     "factor"), 
    length = c(3L, 2L, 1L, 3L), initial = c(6070L, 6150L, 10238L, 
    10260L), final = c(6113, 6163, 10242, 10317)), .Names = c("Id", 
"system", "length", "initial", "final"), class = "data.frame",     row.names = c(NA, 
-4L))
分组是按Id进行的,“系统”字段中的差异(行之间)等于1。此外,我还想了解不同的“系统”,以及其中有多少涉及分组。最后是一个包含第一个“首字母”和最后一个“最终字母”的专栏

在r中有可能做到这一点吗?
谢谢。

您可以使用
数据表。将“data.frame”转换为“data.table”(
setDT
),将“system”(
diff(system)
)的相邻元素之差,
cumsum
作为逻辑向量,创建一个分组变量“indx”,使用“Id”和“indx”作为分组变量获得统计信息

library(data.table)
 setDT(df)[,list(system=toString(system), length=.N, initial=initial[1L],
  final=final[.N]), by=list(Id,indx=cumsum(c(TRUE, diff(system)!=1)))][,
   indx:=NULL][]

#      Id    system length initial final
#1: 16001 9, 10, 11      3    6070  6113
#2: 16971    10, 11      2    6150  6163
#3:  4118         7      1   10238 10242
#4:  4118 9, 10, 11      3   10260 10317
或者根据@jazzurro关于使用
dplyr
中的
first/last
函数的评论

 library(dplyr)
 df %>% 
    group_by(indx=cumsum(c(TRUE, diff(system)!=1)), Id) %>% 
    summarise(system=toString(system), length=n(), 
    initial=first(initial), final=last(final))

没有数据的解决方案。表
,但plyr:

library(plyr)

func = function(subdf)
{
    bool = c(diff(subdf$system),1)==1
    ldply(split(subdf, bool), function(u){
        data.frame(system = paste(u$system, collapse=','),
                   Id     = unique(u$Id),
                   length = nrow(u),
                   initial= head(u,1)$initial,
                   final  = tail(u,1)$final)
    })
}


ldply(split(df, df$Id), func)

#    .id  system length    Id initial final
#1 FALSE       7      1  4118   10238 10242
#2  TRUE 9,10,11      3  4118   10260 10317
#3  TRUE 9,10,11      3 16001    6070  6113
#4  TRUE   10,11      2 16971    6150  6163

使用
first()
last()
是否可以作为另一种选择
first()
是来自dplyr的。@jazzurro我认为它很管用。您可以将其作为dplyr解决方案发布。我仍然想知道在
data.table
中使用
dplyr
中的一些函数是否是一件好事。
dplyr
解决方案将只是对代码的翻译。如果你愿意写一篇,请继续。我将把它留给你。:)@jazzurro我认为dplyr函数应该在这里工作
setDT(df)[,list(system=toString(system),length=.N,initial=first(initial),final=last(final)),by=list(Id,indx=cumsum(c(TRUE,diff(system)!=1))
我刚刚确认了这一点。感谢您测试此想法。:)