我们可以使用
data.table
中的
rleid
函数。
我们将“data.frame”转换为“data.table”。从“key”列创建另一个分组列“ind”。按“id”和“ind”进行分组,得到“value”的总和,并获取“key”的第一个元素。由于预期输出不需要“ind”,因此我们可以将其赋值为NULL。
library(data.table)
setDT(df1)[,list(value = sum(value), key=key[1L]),
by = .(ind=rleid(key), id)][, ind:=NULL][]
或者,如@Frank所建议的那样,我们可以在rleid
内使用多个列,将其用作分组变量,获取其他变量的第一个元素和'value'的sum
,将不需要的列分配给NULL
以避免复制。
setDT(df1)[, list(id=id[1L], key=key[1L], value=sum(value)) ,
by = .(r=rleid(id, key))][, r:= NULL][]
或者我们可以使用 dplyr
。通过比较'key'的相邻元素,我们创建分组变量'ind',并使用summarise
获取'value'的sum
和'key'的first
元素。
library(dplyr)
df1 %>%
group_by(ind= cumsum(key!=lag(key, default=TRUE)), id) %>%
summarise(value=sum(value), key=first(key)) %>%
ungroup() %>%
select(-ind)
注意:在
dplyr
和
data.table
中,我们还可以将“key”列作为分组变量,并删除
key=key[1L]
或
key=first(key))
。
或者我们通过创建“ind”列来
transform
数据集,并使用
base R
中的
aggregate
来获得期望的输出。
df1 <- transform(df1, ind = cumsum(c(TRUE,head(key,-1)!=tail(key,-1))))
aggregate(value~., df1, FUN=sum)[-3]
数据
df1 <- structure(list(id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L), key = c("A",
"A", "B", "A", "A", "B", "C"), value = c(1000L, 2000L, 2001L,
2002L, 2004L, 2002L, 2002L)), .Names = c("id", "key", "value"
), class = "data.frame", row.names = c(NA, -7L))
id
排序?值得一提的是,rleid
可以接受两个参数,解决了这个问题:DT[, .(id=id[1],key=key[1],value=sum(value)), by=.(r=rleid(id,key))][,!"r",with=FALSE]
- Frank