R循环/套用,累积总数与分组依据

时间:2018-11-21 14:26:04

标签: r data.table lapply cumsum cumulative-sum

我正在尝试在数据集中创建新的变量,这些变量是基于其他变量(使用group by)重新启动的累积总计……我希望这些变量成为数据集中的新列,这是我在努力的部分...

使用下面的数据,我想创建将对每个Product和Product_Cat分组重新启动的累积Sales和Profit列。

下面的代码部分地满足了我的需要,但是这些变量不是新变量,而是覆盖了现有的Sale / Profit ...我怎么了?我想这很简单,什么都没找到。

注意:我使用lapply是因为我的真实数据集有40多个varb,我需要为其创建计算。

DT <- setDT(Data)[,lapply(.SD, cumsum), by = .(Product,Product_Cat) ]

数据例如:

Product <- c('A','A','A','B','B','B','C','C','C')
Product_Cat <- c('S1','S1','S2','C1','C1','C1','D1','E1','F1')
Sale <- c(10,15,5,20,15,10,5,5,5)
Profit <- c(2,4,2,6,8,2,4,6,8)
Sale_Cum <- c(10,25,5,20,35,45,5,5,5)
Profit_Cum <- c(2,6,2,6,14,16,4,6,8)

Data <- data.frame(Product,Product_Cat,Sale,Profit)
Desired_Data <- data.frame(Product,Product_Cat,Sale,Profit,Sale_Cum,Profit_Cum)

4 个答案:

答案 0 :(得分:1)

这本身并没有使用该组,但我认为它可以实现您想要的目标,因为它可以轻松扩展到许多列:

D2 <- data.frame(lapply(Data[,c(3,4)], cumsum))
names(D2) <- gsub("$", "_cum", names(Data[,c(3,4)]))
Data <- cbind(Data, D2)

如果您有40列以上,只需更改c(3,4)即可包含您要查找的所有列。

编辑:

我忘记了OP希望为每个类别重置它。在这种情况下,您可以修改原始代码:

DT <- setDT(Data)[,lapply(.SD, cumsum), by = .(Product,Product_Cat) ]
names(D2)[c(-1,-2)] <- gsub("$", "_cum", names(Data)[c(-1,-2)])
cbind(Data, D2[,c(-1,-2)])

答案 1 :(得分:1)

数据:

structure(list(Product = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 
3L, 3L, 3L), .Label = c("A", "B", "C"), class = "factor"), Product_Cat = structure(c(5L, 
5L, 6L, 1L, 1L, 1L, 2L, 3L, 4L), .Label = c("C1", "D1", "E1", 
"F1", "S1", "S2"), class = "factor"), Sale = c(10L, 15L, 5L, 
20L, 15L, 10L, 5L, 5L, 5L), Profit = c(2L, 4L, 2L, 6L, 8L, 2L, 
4L, 6L, 8L), Sale_Cum = c(10, 25, 5, 20, 35, 45, 5, 5, 5), Profit_Cum = c(2, 
6, 2, 6, 14, 16, 4, 6, 8)), .Names = c("Product", "Product_Cat", 
"Sale", "Profit", "Sale_Cum", "Profit_Cum"), row.names = c(NA, 
-9L), class = "data.frame")`

我们可以基于ProductProduct_Cat迭代切片数据帧,对于每次迭代,将cumsum()产生的输出分配给Sale_CumProduct_Cum

cols <- c('Sale', 'Profit')

for (column in cols){
  x[, paste0(column, '_Cum')] <- 0
  for(p in unique(x$Product)){
    for (pc in unique(x$Product_Cat)){
      x[x$Product == p & x$Product_Cat == pc, paste0(column, '_Cum')] <- cumsum(x[x$Product == p & x$Product_Cat == pc, column])
    }
  }
}
print(x)
# Product Product_Cat Sale Profit Sale_Cum Profit_Cum
# 1       A          S1   10      2       10          2
# 2       A          S1   15      4       25          6
# 3       A          S2    5      2        5          2
# 4       B          C1   20      6       20          6
# 5       B          C1   15      8       35         14
# 6       B          C1   10      2       45         16
# 7       C          D1    5      4        5          4
# 8       C          E1    5      6        5          6
# 9       C          F1    5      8        5          8

答案 2 :(得分:1)

library(data.table)
setDT(Data)

cols <- names(Data)[3:4]

Data[, paste0(cols, '_cumsum') := lapply(.SD, cumsum)
     , by = .(Product, Product_Cat) 
     , .SDcols = cols]

答案 3 :(得分:0)

下面是一些很差的代码,无法一步一步完成

#sample data
d<-sample(1:10)
f<-sample(1:10)
p<-c("f","f","f","f","q","q","q","w","w","w")
pc<-c("c","c","d","d","d","v","v","v","b","b")
cc<-data.table(p,pc,d,f)

#storing the values that are overwritten first.
three<-cc[,3]
four<- cc[,4]
#applying your function 
dt<-setDT(c)[,lapply(.SD,cumsum), by=.(p,pc)]

#binding the stored values to your function and renaming everything.
x<-cbind(dt,three,four)
colnames(x)[5]<-"sale"
colnames(x)[6]<-"profit"
colnames(x)[4]<-"CumSale"
colnames(x)[3]<-"CumProfit"

#reordering the columns
xx<-x[,c("p","pc","profit","sale","CumSale","CumProfit")]
xx