Вот базовое решение R:
- определить пользовательскую функцию для группировки
f <- function(v, th = 3) {
k <- 1
r <- c()
repeat {
if (length(v)==0) break
ind<-seq(head(which(cumsum(v)>=th),1))
if (sum(v)<2*th) {
r <- c(r,rep(k,length(v)))
v <- c()
} else {
r <- c(r,rep(k,length(ind)))
v <- v[-ind]
}
k <- k+1
}
r
}
затем используйте
aggregate
+
ave
dfout <- subset(aggregate(Terms~.,
within(within(df,grp <- ave(Number,Classe, Variables, FUN = f)),
Number <- ave(Number,Classe,Variables,grp,FUN = sum)),
c),
select = -grp)
отформатируйте
dfout
до нужного стиля, используя
order
dfout <- dfout[order(dfout$Classe,dfout$Variables),]
Выход
> dfout
Classe Variables Number Terms
3 1 DAT_1 5 20160701q
4 1 DAT_1 3 20160802q, 20160901q
1 1 DAT_2 3 20161001q, 20161201q
5 1 DAT_2 3 20170301q
2 2 DAT_1 4 20161001q, 20161201q, 20170301q
DATA
df <- structure(list(Classe = c(1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L),
Variables = c("DAT_1", "DAT_1", "DAT_1", "DAT_2", "DAT_2",
"DAT_2", "DAT_1", "DAT_1", "DAT_1"), Terms = c("20160701q",
"20160802q", "20160901q", "20161001q", "20161201q", "20170301q",
"20161001q", "20161201q", "20170301q"), Number = c(5L, 2L,
1L, 1L, 2L, 3L, 1L, 2L, 1L)), class = "data.frame", row.names = c(NA,
-9L))
ОБНОВЛЕНИЕ Если вы хотите объединить содержимое в Terms
, попробуйте код ниже
dfout <- subset(aggregate(Terms~.,
within(within(df,grp <- ave(Number,Classe, Variables, FUN = f)),
Number <- ave(Number,Classe,Variables,grp,FUN = sum)),
FUN = function(v) ifelse(length(v)==1,v,paste0(c(v[1],v[length(v)]),collapse = "-"))),
select = -grp)
dfout <- dfout[order(dfout$Classe,dfout$Variables),]
, такой что
> dfout
Classe Variables Number Terms
3 1 DAT_1 5 20160701q
4 1 DAT_1 3 20160802q-20160901q
1 1 DAT_2 3 20161001q-20161201q
5 1 DAT_2 3 20170301q
2 2 DAT_1 4 20161001q-20170301q