我有一张表格如下: DF
KEY CAT DATE AMOUNT VAR VALUE
1 26 2015/10/1 1400 Event.Budget_Cat26 NA
1 26 2015/10/1 300 Event.Budget_Cat26 NA
1 26 2015/10/1 NA NA NA
1 22 2015/10/1 100 Event.Budget_Cat22 NA
1 22 2015/10/1 300 Event.Budget_Cat22 NA
1 22 2015/10/1 NA NA NA
2 21 2014/1/1 200 Event.Budget_Cat21 NA
2 21 2014/1/1 NA NA NA
这只是大表的一部分。基本上,每一行都是唯一的(KEY,CAT,DATE)。我想找到一种基于唯一标识来计算金额总和的方法,并将最终总和放入VALUE列。 另外,给VAR命名。 AMOUNT列仅存在于VALUE列中,我将最后删除整列,因此将其保留为NA即可。
最终结果将是
KEY CAT DATE AMOUNT VAR VALUE
1 26 2015/10/1 1400 Event.Budget_Cat26 NA
1 26 2015/10/1 300 Event.Budget_Cat26 NA
1 26 2015/10/1 NA Scalar.Budget_Cat26_Amt 1700
1 22 2015/10/1 100 Event.Budget_Cat22 NA
1 22 2015/10/1 300 Event.Budget_Cat22 NA
1 22 2015/10/1 NA Scalar.Budget_Cat22_Amt 400
2 21 2014/1/1 200 Event.Budget_Cat21 NA
2 21 2014/1/1 NA Scalar.Budget_Cat21_Amt 200
我试过rbind和lapply,但结果不是我想要的
df[, 4:6 := lapply(.SD,
function(x) replace(x, is.na(x), c("",paste("Scalar_Budget_Cat",CAT,"_Amt",sep =""),sum(x, na.rm=TRUE))),
KEY, .SDcols=4]
有没有人可以帮我找出一个快速的方法来运行整个数据表,其中包含2,600,000行?谢谢
答案 0 :(得分:1)
根据“KEY”,“CAT”,“DATE”进行分组后,有多种方法可以使用sum
'AMOUNT'创建'VALUE',然后根据是否将这些值更改为NA
它不是组的最后一个值。我们使用rep
为'VALUE'列创建NA
和sum
'AMOUNT',并修改'VAR'列以获得每个组的最后一个元素,而不是这样做使用`Scalar'子串
setDT(df1)[, c("VAR", "VALUE") := .(c(VAR[-.N], paste0("Scalar.",
sub("^[^.]+\\.", "", VAR[1]), "_Amt")), rep(c(NA, sum(AMOUNT, na.rm = TRUE)),
c(.N-1, 1))), .(KEY, CAT, DATE)]
df1
# KEY CAT DATE AMOUNT VAR VALUE
#1: 1 26 2015/10/1 1400 Event.Budget_Cat26 NA
#2: 1 26 2015/10/1 300 Event.Budget_Cat26 NA
#3: 1 26 2015/10/1 NA Scalar.Budget_Cat26_Amt 1700
#4: 1 22 2015/10/1 100 Event.Budget_Cat22 NA
#5: 1 22 2015/10/1 300 Event.Budget_Cat22 NA
#6: 1 22 2015/10/1 NA Scalar.Budget_Cat22_Amt 400
#7: 2 21 2014/1/1 200 Event.Budget_Cat21 NA
#8: 2 21 2014/1/1 NA Scalar.Budget_Cat21_Amt 200
答案 1 :(得分:1)
我在260万行上尝试过,它真的很快。我们将任务拆分为两个操作。第一个是按KEY
,CAT
和DATE
对行进行分组,然后对AMOUNT
列求和。之后,我们选择is.na(VAR) == T
的行,并用相应的字符串填充VAR
列。
df[, VALUE:=sum(AMOUNT, na.rm = T),by=list(KEY, CAT, DATE)][is.na(VAR), VAR:=paste0("Scalar_Budget_Cat",CAT,"_Amt"),]
与所需输出的差异在于NA
中不再有VALUE
个值。但是之后可以使用df[!is.na(AMOUNT), VALUE:=NA,]
答案 2 :(得分:0)
以下是tidyverse
的解决方案:
library(tidyverse)
KEY <- c(1, 1, 1, 1, 1, 1, 2, 2)
CAT <- c(26, 26, 26, 22, 22, 22, 21,21)
DATE <- c('2015/10/1', '2015/10/1', '2015/10/1', '2015/10/1', '2015/10/1', '2015/10/1', '2014/1/1', '2014/1/1')
AMOUNT <- c(1400, 300, NA, 100, 300, NA, 200, NA)
VAR <- c('Event.Budget_Cat26', 'Event.Budget_Cat26', NA, 'Event.Budget_Cat22', 'Event.Budget_Cat22', NA, 'Event.Budget_Cat21', NA)
df <- data_frame(KEY, CAT, DATE, AMOUNT, VAR, VALUE = NA)
summary_rows <- df %>%
group_by(KEY, CAT, DATE) %>%
summarise(VAR = paste0('Scalar.Budget_Cat', max(CAT), '_Amt'),
VALUE = sum(AMOUNT, na.rm = T),
AMOUNT = NA) %>%
select(KEY, CAT, DATE, AMOUNT, VAR, VALUE) %>%
arrange(KEY, -CAT, DATE)
df[is.na(AMOUNT),] <- summary_rows
df
## KEY CAT DATE AMOUNT VAR VALUE
## <dbl> <dbl> <chr> <dbl> <chr> <dbl>
## 1 1 26 2015/10/1 1400 Event.Budget_Cat26 NA
## 2 1 26 2015/10/1 300 Event.Budget_Cat26 NA
## 3 1 26 2015/10/1 NA Scalar.Budget_Cat26_Amt 1700
## 4 1 22 2015/10/1 100 Event.Budget_Cat22 NA
## 5 1 22 2015/10/1 300 Event.Budget_Cat22 NA
## 6 1 22 2015/10/1 NA Scalar.Budget_Cat22_Amt 400
## 7 2 21 2014/1/1 200 Event.Budget_Cat21 NA
## 8 2 21 2014/1/1 NA Scalar.Budget_Cat21_Amt 200