R 对每个 id 的每个 class 求和

R summing up total for each class for each id

假设我有这样的数据集:

df <- data.frame(id = c(1, 1, 1, 2, 2),
      classname = c("Welding", "Welding", "Auto", "HVAC", "Plumbing"),
      hours = c(3, 2, 4, 1, 2))  

   id  classname  hours
1   1   Welding     3
2   1   Welding     2
3   1   Auto        4
4   2   HVAC        1
5   2   Plumbing    2

我想弄清楚如何以一种方式总结数据,为每个 ID 提供他们花费的 classes 的列表以及每个 class。我希望这些列在一个列表中,这样我就可以将每个 ID 保留一行。所以,我希望它 return:

   id     class.list     class.hours
1   1    Welding, Auto       5,4   
2   2    HVAC, Plumbing      1,2    

我能够弄清楚如何将它发送到 return class.list。

library(dplyr)
classes <- df %>%
group_by(id) %>%
summarise(class.list = list(unique(as.character(classname)))) 

这给了我:

   id     class.list     
1   1    Welding, Auto         
2   2    HVAC, Plumbing      

但我不确定如何计算每个 class 的小时数 (class.hours)。

感谢您的帮助!

在 base R 中,这可以通过两次调用 aggregate 来完成。内部调用对小时数求和,外部调用 "concatenates" 小时数和 class 名称。在 aggregate 的外部调用中,cbind 用于在输出中包含小时和 class 名称,并提供所需的变量名称。

# convert class name to character variable
df$classname <- as.character(df$classname)
# aggregate
aggregate(cbind("class.hours"=hours, "class.list"=classname)~id,
          data=aggregate(hours~id+classname, data=df, FUN=sum), toString)
  id class.hours     class.list
1  1        4, 5  Auto, Welding
2  2        1, 2 HVAC, Plumbing

data.table中,链式语句产生大致相同的输出。

setDT(df)[, .(hours=sum(hours)), by=.(id, classname)][, lapply(.SD, toString), by=id]
   id      classname hours
1:  1  Welding, Auto  5, 4
2:  2 HVAC, Plumbing  1, 2

然后可以使用 data.table setnames 函数设置变量名称。

这是使用 dplyr 的方法:

classes <- df %>%
  group_by(id, classname) %>%
  summarise(hours = sum(hours)) %>%
  summarise(class.list = list(unique(as.character(classname))),
            class.hours = list(hours)) 

第一个总结最新分组的peels by (classname)。没有必要再使用 unique() 了,但我把它放在那里以匹配你已经拥有的部分。