2015-03-10 21 views
6

otrzymuje następujące data.table z danych finansowych:Dane finansowe - R data.table - grupa przez condiction

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 

Chcę grupy przez userId, systemBankId, accountId i quantity:

dt[userId==871L,.N,by=.(userId,systemBankId,accountId,quantity)] 

Wynik jest następujący:

userId systemBankId accountId quantity N 
    871   0065  6422 -52400  3 
    871   0065  6422 -3000000  1 
    871   0065  6422 -52349 20 

Ale pierwsza i trzecia to ta sama transakcja: spłata kredytu hipotecznego, a druga to pożyczka.

Chcę przez grupy w następujący sposób:

userId systemBankId accountId quantity N 
    871   0065  6422 -XXXXX 23 
    871   0065  6422 -3000000 1 

Więc widać, że w ciągu 24 miesięcy tego użytkownik ma 23 transakcji hipotecznych i 1 płatność transakcji pożyczki.

Pytanie brzmi: czy istnieje prosty sposób na zrobienie tego? (tj.):

dt[userId==871L,.N,by=.(userId,systemBankId,accountId,(quantity %between% c(-quantity*0.20,quantity*0,20))] 

Dla płatności w przedziale [-20%, 20%] uważa się za równe.

Dziękuję w wersji zaawansowanej.

Pozdrawiamy.


Aby uzyskać ramki danych z danymi powyżej:

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)) 

UPDATE

Ostatnim krokiem jest zaznaczenie w oryginalnym zbiorze transakcji, które są płatności hipotecznych i które są spłaty kredytów.

Na podstawie odpowiedzi robię:

a) criterio: w okresie 24 miesięcy ,, jeśli istnieją dwadzieścia lub więcej powtarzające się transakcje przez USERID systemBankId, accountid, ilości (-20%, 20%) są to kredyty hipoteczne:

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 

Wiem, że są 23 transakcje hipoteczne.

b) muszę zidentyfikować 23 transakcji:

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 

Ok mam zidentyfikowano 23 transakcji, ale jeśli mam transacction z ilością równą -52000 zostanie to zaznaczone jakby to była hipoteka płatność też.

Moje pytanie brzmi: w oparciu o kryterium płatności cyklicznej Jak zidentyfikować prawidłowe transakcje.

Thx w wersji zaawansowanej.

+1

W przykładzie, masz tylko 2 '-52400' ilość, a nie 3. –

+5

Coś' DT [userid == 871L, .N, by =. (userId, systemBankId, accountId, ilość = round (ilość * 5, -podłoga (log10 (abs (ilość))))/5)]? – Roland

+1

@Roland powinieneś zamieścić to jako odpowiedź –

Odpowiedz

4

Może smth wzdłuż tych linii:

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 
4

Oto krótki kilof z dplyr:

library(dplyr) 
setDF(dt) %>% mutate(quantity = round(quantity/10000, 0)) %>% 
    group_by(userId, systemBankId, accountId, quantity) %>% tally() 

Co daje:

#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 

Edit

Jak wymieniono przez Dawida w komentarzach, to odpowiedź jest uproszczeniem. Bardziej spójne podejście byłoby coś sugestią Rolanda:

library(dplyr) 
setDF(dt) %>% 
    mutate(quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5) %>% 
    group_by(userId, systemBankId, accountId, quantity) %>% tally() 

lub używając data.table:

dt[userId == 871L, .N, by = .(userId, systemBankId, accountId, quantity = round(quantity * 5, -floor(log10(abs(quantity))))/5)] 
+4

Nie wiesz, dlaczego nie można po prostu nieznacznie zmodyfikować kodów OP do 'dt [userId == 871L, .N, by =. (UserId, systemBankId, accountId, quantity = round (ilość/10000, 0))] ', dlaczego' dplyr'? –

+0

Co z tym, że '[-20%, 20%]' są uważane za równe –

+4

Ta odpowiedź jest również koncepcyjnie błędna, ponieważ przyjmuje się, że płatności morgatge są w 10 tysięcy. Spróbuj 'dt [, ilość: = ilość * 100]', a następnie ponownie uruchom swój kod i zobacz, co się stanie. –

0

Oto sprytna funkcja, która jest istotna stworzony przez @dnlbrky tutaj: 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]) 
    } 

Umożliwi to określenie zakresu 20%:

dt$prev_qty_low <-rowShift(dt$quantity,-1) * .8 
dt$prev_qty_high <-rowShift(dt$quantity,-1) * 1.2