2017-01-16 11 views
13

Mam dwie tabele, które muszę zrobić sumif całej. Tabela 1 zawiera okresy, tj. Rok i kwartał na koniec roku (tj. 4, 8, 12 itp.). Tabela 2 zawiera transakcje w ciągu roku na kwartały 3, 6, 7 itpJak podsumować dwie tabele?

muszę tabela 3 do sumy wszystkich transakcji w ciągu roku, tak aby uzyskać łączny pozycję na koniec roku.

Oto niektóre przykładowy kod, aby wyjaśnić, co dane wygląda i co wyjście powinno wyglądać następująco:

library(data.table) 

x1 <- data.table("Name" = "LOB1", "Year" = 2000, 
       "Quarter" = c(4, 8, 12, 16, 20, 24, 28, 32, 36)) 
x2 <- data.table("Name" = "LOB1", "Year" = 2000, 
       "Quarter" = c(3, 6, 7, 9, 11, 14, 16, 20, 24), 
       "Amount" = c(10000, 15000, -2500, 3500, -6500, 25000, 
           11000, 9000, 7500)) 
x3 <- data.table("Name" = "LOB1", "Year" = 2000, 
       "Quarter" = c(4, 8, 12, 16, 20, 24, 28, 32, 36), 
       "Amount" = c(10000, 22500, 19500, 55500, 64500, 72000, 
           72000, 72000, 72000)) 

Próbowałem merge, summarise, foverlaps ale nie mogę zupełnie zrozumieć.

Odpowiedz

11

Ładne pytanie. Zasadniczo próbujesz połączyć się przez Name, Year i Quarter <= Quarter, jednocześnie sumując wszystkie dopasowane wartości Amount. Jest to możliwe zarówno przy użyciu nowego non-equi przyłącza (które zostały wprowadzone w najnowszej stabilnej wersji data.table v-1.10.0) i foverlaps (a drugi będzie prawdopodobnie nieoptymalne)

Nie- Equi dołącza:

x2[x1, # for each value in `x1` find all the matching values in `x2` 
    .(Amount = sum(Amount)), # Sum all the matching values in `Amount` 
    on = .(Name, Year, Quarter <= Quarter), # join conditions 
    by = .EACHI] # Do the summing per each match in `i` 
# Name Year Quarter Amount 
# 1: LOB1 2000  4 10000 
# 2: LOB1 2000  8 22500 
# 3: LOB1 2000  12 19500 
# 4: LOB1 2000  16 55500 
# 5: LOB1 2000  20 64500 
# 6: LOB1 2000  24 72000 
# 7: LOB1 2000  28 72000 
# 8: LOB1 2000  32 72000 
# 9: LOB1 2000  36 72000 

na marginesie, można łatwo dodać Amount w miejscu x1 (zaproponowany przez @Frank):

x1[, Amount := 
    x2[x1, sum(x.Amount), on = .(Name, Year, Quarter <= Quarter), by = .EACHI]$V1 
] 

Może to być wygodne, jeśli masz więcej niż trzy kolumny sprzężenia w tej tabeli.


foverlaps:

Wspomniałeś foverlaps, więc teoretycznie można osiągnąć to samo przy użyciu tej funkcji też. Chociaż obawiam się, że łatwo zapomnisz o pamięci. Korzystanie foverlaps, trzeba będzie stworzyć ogromny stół, gdzie każda wartość w x2 dołączył kilka razy do każdej wartości w x1 i przechowywać wszystko w pamięci

x1[, Start := 0] # Make sure that we always join starting from Q0 
x2[, Start := Quarter] # In x2 we want to join all possible rows each time 
setkey(x2, Name, Year, Start, Quarter) # set keys 
## Make a huge cartesian join by overlaps and then aggregate 
foverlaps(x1, x2)[, .(Amount = sum(Amount)), by = .(Name, Year, Quarter = i.Quarter)] 
# Name Year Quarter Amount 
# 1: LOB1 2000  4 10000 
# 2: LOB1 2000  8 22500 
# 3: LOB1 2000  12 19500 
# 4: LOB1 2000  16 55500 
# 5: LOB1 2000  20 64500 
# 6: LOB1 2000  24 72000 
# 7: LOB1 2000  28 72000 
# 8: LOB1 2000  32 72000 
# 9: LOB1 2000  36 72000 
+0

Dzięki tak dużo - Właśnie dostałem tej pracy. Bardzo doceniane! Wygląda na to, że obie moje tabele muszą mieć w sobie te same kolumny. Jeśli x2 ma jedną dodatkową kolumnę, której nie chcę uwzględnić w wynikowej tabeli x3, czy kod byłby taki sam? – kodfather

+0

Możesz określić w argumencie 'on' dowolne nazwy kolumn z obu tabel. Na przykład '.on (column1 = column2, column3 = column4)', itp. LHS z suasion są kolumnami z 'x1' podczas gdy RHS z równania są kolumnami z' x2'. –