财务数据 - R data.table - 按条件分组
Financial Data - R data.table - group by condiction
鉴于以下 data.table
财务数据:
userId systemBankId accountId valueDate quantity description
871 0065 6422 2013-02-28 -52400 AMORTIZACION PRESTAMO
871 0065 6422 2013-03-28 -52400 AMORTIZACION PRESTAMO
871 0065 6422 2013-04-01 -3000000 AMORTIZACION PRESTAMO
871 0065 6422 2013-04-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-05-31 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-06-28 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-07-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-08-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-09-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-10-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-11-29 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-12-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-01-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-02-28 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-03-31 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-04-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-05-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-06-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-07-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-08-29 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-09-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-10-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-11-28 -52349 AMORTIZACION PRESTAMO
我想按 userId
、systemBankId
、accountId
和 quantity
进行分组:
dt[userId==871L,.N,by=.(userId,systemBankId,accountId,quantity)]
结果如下:
userId systemBankId accountId quantity N
871 0065 6422 -52400 3
871 0065 6422 -3000000 1
871 0065 6422 -52349 20
但是,第一个和第三个是同一笔交易:按揭付款,第二个是贷款。
我想按以下方式分组:
userId systemBankId accountId quantity N
871 0065 6422 -XXXXX 23
871 0065 6422 -3000000 1
因此您可以看到,在 24 个月内,该用户有 23 笔抵押交易和 1 笔贷款交易付款。
问题是:有没有简单的方法来做到这一点? (即):
dt[userId==871L,.N,by=.(userId,systemBankId,accountId,(quantity %between% c(-quantity*0.20,quantity*0,20 ))]
[-20%,20%] 范围内的付款被视为相等。
先谢谢你。
此致。
获取上面数据的数据框:
structure(list(userId = c(871L, 871L, 871L, 871L, 871L, 871L,
871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L,
871L, 871L, 871L, 871L, 871L, 871L), systemBankId = c(65L, 65L,
65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L,
65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L), accountId = c(6422L,
6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L,
6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L,
6422L, 6422L, 6422L, 6422L), valueDate = structure(c(2L, 4L,
1L, 10L, 23L, 5L, 14L, 16L, 17L, 19L, 8L, 21L, 9L, 3L, 22L, 11L,
12L, 13L, 15L, 7L, 18L, 20L, 6L), .Label = c("01/04/2013", "28/02/2013",
"28/02/2014", "28/03/2013", "28/06/2013", "28/11/2014", "29/08/2014",
"29/11/2013", "30/01/2014", "30/04/2013", "30/04/2014", "30/05/2014",
"30/06/2014", "30/07/2013", "30/07/2014", "30/08/2013", "30/09/2013",
"30/09/2014", "30/10/2013", "30/10/2014", "30/12/2013", "31/03/2014",
"31/05/2013"), class = "factor"), quantity = c(-52400L, -52400L,
-3000000L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L,
-52349L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L,
-52349L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L
), description = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "AMORTIZACION PRESTAMO", class = "factor")), .Names = c("userId",
"systemBankId", "accountId", "valueDate", "quantity", "description"
), class = "data.frame", row.names = c(NA, -23L))
U P D A T E
最后一步是在原始数据集中标记为抵押付款和贷款付款的交易。
根据我的回答:
a) 标准:在 24 个月的时间段内,如果按 userId、systemBankId、accountId、数量(-20%、20%)有二十个或更多的经常性交易,则它们是抵押付款:
tmp <- dt[userId==871L,.N,by=.(userId,systemBankId,accountId,round(quantity * 5, -floor(log10(abs(quantity))))/5)][N>20,list(userId,systemBankId,accountId,round,N)]
userId systemBankId accountId round N
871 0065 6422 -52000 23
我知道有 23 个抵押交易。
b) 我需要识别这 23 笔交易:
tmp2 <- dt[userId==871L,list(userId,systemBankId,accountId,round=round(quantity * 5, -floor(log10(abs(quantity))))/5)]
merge(tmp,tmp2,by=c('userId','systemBankId','accountId','round'))
userId systemBankId accountId round N
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
userId systemBankId accountId round N
好的,我已经确定了 23 笔交易,但如果我有一笔交易的数量等于 -52000,这也会被标记为抵押贷款付款。
我的问题是:根据经常性付款的标准,我如何识别正确的交易。
提前致谢。
这是 dplyr
的快速技巧:
library(dplyr)
setDF(dt) %>% mutate(quantity = round(quantity/10000, 0)) %>%
group_by(userId, systemBankId, accountId, quantity) %>% tally()
给出:
#Source: local data frame [2 x 5]
#Groups: userId, systemBankId, accountId
#
# userId systemBankId accountId quantity n
#1 871 65 6422 -300 1
#2 871 65 6422 -5 22
编辑
正如 David 在评论中提到的那样,这个答案过于简单化了。更一致的方法类似于 Roland 的建议:
library(dplyr)
setDF(dt) %>%
mutate(quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5) %>%
group_by(userId, systemBankId, accountId, quantity) %>% tally()
或使用data.table
:
dt[userId == 871L, .N, by = .(userId, systemBankId, accountId, quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5)]
这是@dnlbrky 在这里创建的一个相关的聪明函数:Use a value from the previous row in an R data.table calculation
#Create a function to return previous rows
rowShift <- function(x, shiftLen = 1L) {
r <- (1L + shiftLen):(length(x) + shiftLen)
r[r<1] <- NA
return(x[r])
}
这将让您确定 20% 的范围:
dt$prev_qty_low <-rowShift(dt$quantity,-1) * .8
dt$prev_qty_high <-rowShift(dt$quantity,-1) * 1.2
大概是这样的:
dt[, round.qty := quantity[1] * round(quantity/quantity[1]), by = .(userId, systemBankId, accountId)]
dt[, .N, by = .(userId, systemBankId, accountId, round.qty)]
# userId systemBankId accountId round.qty N
#1: 871 65 6422 -52400 22
#2: 871 65 6422 -2986800 1
鉴于以下 data.table
财务数据:
userId systemBankId accountId valueDate quantity description
871 0065 6422 2013-02-28 -52400 AMORTIZACION PRESTAMO
871 0065 6422 2013-03-28 -52400 AMORTIZACION PRESTAMO
871 0065 6422 2013-04-01 -3000000 AMORTIZACION PRESTAMO
871 0065 6422 2013-04-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-05-31 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-06-28 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-07-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-08-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-09-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-10-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-11-29 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2013-12-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-01-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-02-28 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-03-31 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-04-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-05-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-06-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-07-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-08-29 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-09-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-10-30 -52349 AMORTIZACION PRESTAMO
871 0065 6422 2014-11-28 -52349 AMORTIZACION PRESTAMO
我想按 userId
、systemBankId
、accountId
和 quantity
进行分组:
dt[userId==871L,.N,by=.(userId,systemBankId,accountId,quantity)]
结果如下:
userId systemBankId accountId quantity N
871 0065 6422 -52400 3
871 0065 6422 -3000000 1
871 0065 6422 -52349 20
但是,第一个和第三个是同一笔交易:按揭付款,第二个是贷款。
我想按以下方式分组:
userId systemBankId accountId quantity N
871 0065 6422 -XXXXX 23
871 0065 6422 -3000000 1
因此您可以看到,在 24 个月内,该用户有 23 笔抵押交易和 1 笔贷款交易付款。
问题是:有没有简单的方法来做到这一点? (即):
dt[userId==871L,.N,by=.(userId,systemBankId,accountId,(quantity %between% c(-quantity*0.20,quantity*0,20 ))]
[-20%,20%] 范围内的付款被视为相等。
先谢谢你。
此致。
获取上面数据的数据框:
structure(list(userId = c(871L, 871L, 871L, 871L, 871L, 871L,
871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L, 871L,
871L, 871L, 871L, 871L, 871L, 871L), systemBankId = c(65L, 65L,
65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L,
65L, 65L, 65L, 65L, 65L, 65L, 65L, 65L), accountId = c(6422L,
6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L,
6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L, 6422L,
6422L, 6422L, 6422L, 6422L), valueDate = structure(c(2L, 4L,
1L, 10L, 23L, 5L, 14L, 16L, 17L, 19L, 8L, 21L, 9L, 3L, 22L, 11L,
12L, 13L, 15L, 7L, 18L, 20L, 6L), .Label = c("01/04/2013", "28/02/2013",
"28/02/2014", "28/03/2013", "28/06/2013", "28/11/2014", "29/08/2014",
"29/11/2013", "30/01/2014", "30/04/2013", "30/04/2014", "30/05/2014",
"30/06/2014", "30/07/2013", "30/07/2014", "30/08/2013", "30/09/2013",
"30/09/2014", "30/10/2013", "30/10/2014", "30/12/2013", "31/03/2014",
"31/05/2013"), class = "factor"), quantity = c(-52400L, -52400L,
-3000000L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L,
-52349L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L,
-52349L, -52349L, -52349L, -52349L, -52349L, -52349L, -52349L
), description = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), .Label = "AMORTIZACION PRESTAMO", class = "factor")), .Names = c("userId",
"systemBankId", "accountId", "valueDate", "quantity", "description"
), class = "data.frame", row.names = c(NA, -23L))
U P D A T E
最后一步是在原始数据集中标记为抵押付款和贷款付款的交易。
根据我的回答:
a) 标准:在 24 个月的时间段内,如果按 userId、systemBankId、accountId、数量(-20%、20%)有二十个或更多的经常性交易,则它们是抵押付款:
tmp <- dt[userId==871L,.N,by=.(userId,systemBankId,accountId,round(quantity * 5, -floor(log10(abs(quantity))))/5)][N>20,list(userId,systemBankId,accountId,round,N)]
userId systemBankId accountId round N
871 0065 6422 -52000 23
我知道有 23 个抵押交易。
b) 我需要识别这 23 笔交易:
tmp2 <- dt[userId==871L,list(userId,systemBankId,accountId,round=round(quantity * 5, -floor(log10(abs(quantity))))/5)]
merge(tmp,tmp2,by=c('userId','systemBankId','accountId','round'))
userId systemBankId accountId round N
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
871 0065 6422 -52000 23
userId systemBankId accountId round N
好的,我已经确定了 23 笔交易,但如果我有一笔交易的数量等于 -52000,这也会被标记为抵押贷款付款。
我的问题是:根据经常性付款的标准,我如何识别正确的交易。
提前致谢。
这是 dplyr
的快速技巧:
library(dplyr)
setDF(dt) %>% mutate(quantity = round(quantity/10000, 0)) %>%
group_by(userId, systemBankId, accountId, quantity) %>% tally()
给出:
#Source: local data frame [2 x 5]
#Groups: userId, systemBankId, accountId
#
# userId systemBankId accountId quantity n
#1 871 65 6422 -300 1
#2 871 65 6422 -5 22
编辑
正如 David 在评论中提到的那样,这个答案过于简单化了。更一致的方法类似于 Roland 的建议:
library(dplyr)
setDF(dt) %>%
mutate(quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5) %>%
group_by(userId, systemBankId, accountId, quantity) %>% tally()
或使用data.table
:
dt[userId == 871L, .N, by = .(userId, systemBankId, accountId, quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5)]
这是@dnlbrky 在这里创建的一个相关的聪明函数:Use a value from the previous row in an R data.table calculation
#Create a function to return previous rows
rowShift <- function(x, shiftLen = 1L) {
r <- (1L + shiftLen):(length(x) + shiftLen)
r[r<1] <- NA
return(x[r])
}
这将让您确定 20% 的范围:
dt$prev_qty_low <-rowShift(dt$quantity,-1) * .8
dt$prev_qty_high <-rowShift(dt$quantity,-1) * 1.2
大概是这样的:
dt[, round.qty := quantity[1] * round(quantity/quantity[1]), by = .(userId, systemBankId, accountId)]
dt[, .N, by = .(userId, systemBankId, accountId, round.qty)]
# userId systemBankId accountId round.qty N
#1: 871 65 6422 -52400 22
#2: 871 65 6422 -2986800 1