R dplyr совокупное количество или количество в течение интервала времени в минутах - PullRequest
0 голосов
/ 25 июня 2018

У меня есть набор данных, который состоит из date_time, аккаунта (оба символа) и суммы (числовой), как показано ниже:

sample data:
    date_time <- as.character(c('2018-01-22 18:18:00','2018-01-22 18:18:05','2018-01-22 18:18:19','2018-01-22 18:18:00','2018-01-22 18:30:12','2018-01-22 18:18:11'))
    account <- as.character(c('a0001','a0001','a0001','b0001','b0001','c0001'))
    amount <- c(1000,200,300,10000,400,10000)
    df.sample <- data.frame(date_time, account, amount)

Я хотел бы вернуть значение ИСТИНА, если для транзакции с таким суммарным счетом> = 2 И общая сумма> = 12000 в течение 1 минуты для каждого аккаунта, В противном случае - ЛОЖЬ.

Я написал функцию, используя dplyr, как показано ниже:

simulation <- function(df, v.acct, v.date.time) {

  # v.acct <- '5408044133161021'
  # v.date.time <- as.POSIXct('2018-01-22 18:18:11')
  #time.interval <- 120

  #subset
  df2 <- df %>% 
          mutate(date.time=as.POSIXct(date_time),
                 diff.time=difftime(v.date.time, date.time, units=c('mins'))) %>%
          filter(account %in% v.acct,  diff.time <= time.interval, diff.time > 0) 

  df.summary <- df2 %>% 
                  group_by(account) %>%
                  summarise(agg.cnt=n(),
                            agg.amt=sum(amount))

  nrow <- df.summary %>% filter(agg.cnt>=agg.count, agg.amt>=agg.amount) %>% nrow()

  result <- ifelse(nrow==0, FALSE, TRUE)

  return(result)

}

И вектор будет возвращен, которые содержат ИСТИНА или ЛОЖЬ:

time.interval <- 10
agg.count <- 10
agg.amount <- 20000
v.result <- apply(df[,c(1,2)],1,function(x) simulation(x[2],x[1]))

Выпуск: Выше кода, способного вернуть результат, в то время как если набор данных станет более 90000 наблюдений, время вычислений будет очень большим. Есть ли альтернативный метод? Спасибо

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Это может быть возможным решением:

   library(data.table)
    library(lubridate)
    library(zoo)
    setDT(df)
    df[, date.time := as.POSIXct(date_time, format="%Y-%m-%d %H:%M:%S")]
    df[, time.diff := difftime(date.time,min(date.time), units='mins')+0.0001, by=account]
    df[, interval := ceiling(time.diff / dminutes(time.interval)), by=account]
    df[, agg.cnt:=seq_len(.N), by=.(account, interval)]
    df[, agg.amt2:=cumsum(amount), by=.(account, interval)]
0 голосов
/ 25 июня 2018

Предполагая, что OP не возражает против решения data.table, вы можете использовать неравное самостоятельное объединение, чтобы найти экземпляры, которые выпадают в течение 1 минуты каждой транзакции (by=.EACHI говорит data.table выполнить объединение для каждой строки данных в i=df. См. ?data.table, чтобы увидеть, что означают i и .EACHI.

Затем проверьте, является ли счет больше или равным agg.count и если общая сумма больше или равна agg.amount

данные:

date_time <- as.character(c('2018-01-22 18:18:00','2018-01-22 18:18:05','2018-01-22 18:18:19','2018-01-22 18:18:00','2018-01-22 18:30:12','2018-01-22 18:18:11'))
account <- c('a0001','a0001','a0001','b0001','b0001','c0001')
amount <- c(1000,200,300,10000,400,10000)
df <- data.frame(date_time, account, amount)

time.interval <- 60
agg.count <- 10
agg.amount <- 20000

код:

library(data.table)
setDT(df)
df[, date_time := as.POSIXct(date_time, format="%Y-%m-%d %H:%M:%S")]
df[, oneMinLater := date_time + time.interval]
df[, hit :=
    df[df, 
    .N >= agg.count & sum(amount, na.rm=TRUE) >= agg.amount,
    by=.EACHI, 
    on=.(account, date_time > date_time, date_time <= oneMinLater)]$V1
]

выход:

             date_time account amount         oneMinLater   hit
1: 2018-01-22 18:18:00   a0001   1000 2018-01-22 18:19:00 FALSE
2: 2018-01-22 18:18:05   a0001    200 2018-01-22 18:19:05 FALSE
3: 2018-01-22 18:18:19   a0001    300 2018-01-22 18:19:19 FALSE
4: 2018-01-22 18:18:00   b0001  10000 2018-01-22 18:19:00 FALSE
5: 2018-01-22 18:30:12   b0001    400 2018-01-22 18:31:12 FALSE
6: 2018-01-22 18:18:11   c0001  10000 2018-01-22 18:19:11 FALSE
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...