2017-03-03 4 views
0

Ich bin ein Anfänger in data.table und suchte nach Join und dann mutieren Spalten. Ich habe data.table join then add columns to existing data.frame without re-copy Thread gefunden, aber ich konnte nicht weiter fortfahren.Join dann mutieren mit data.table ohne Zwischentabelle

Bitte beachten Sie, dass ich in der Lage bin, was ich mit dplyr tun möchte, aber es ist nicht machbar, diesen Code auf die tatsächlichen Daten aufgrund der Größe zu führen. Außerdem kann ich aus dem genannten Grund keine Zwischentabellen erstellen.

Hier sind meine Daten und Lösung dplyr

Eingang

DFI = structure(list(PO_ID = c("P1234", "P1234", "P1234", "P1234", 
"P1234", "P1234", "P2345", "P2345", "P3456", "P4567"), SO_ID = c("S1", 
"S1", "S1", "S2", "S2", "S2", "S3", "S4", "S7", "S10"), F_Year = c(2012, 
2012, 2012, 2013, 2013, 2013, 2011, 2011, 2014, 2015), Product_ID = c("385X", 
"385X", "385X", "450X", "450X", "900X", "3700", "3700", "A11U", 
"2700"), Revenue = c(1, 2, 3, 34, 34, 6, 7, 88, 9, 100), Quantity = c(1, 
2, 3, 8, 8, 6, 7, 8, 9, 40), Location1 = c("MA", "NY", "WA", 
"NY", "WA", "NY", "IL", "IL", "MN", "CA")), .Names = c("PO_ID", 
"SO_ID", "F_Year", "Product_ID", "Revenue", "Quantity", "Location1" 
), row.names = c(NA, 10L), class = "data.frame") 

Look Up Table

DF_Lookup = structure(list(PO_ID = c("P1234", "P1234", "P1234", "P2345", 
"P2345", "P3456", "P4567"), SO_ID = c("S1", "S2", "S2", "S3", 
"S4", "S7", "S10"), F_Year = c(2012, 2013, 2013, 2011, 2011, 
2014, 2015), Product_ID = c("385X", "450X", "900X", "3700", "3700", 
"A11U", "2700"), Revenue = c(50, 70, 35, 100, -50, 50, 100), 
    Quantity = c(3, 20, 20, 20, -10, 20, 40)), .Names = c("PO_ID", 
"SO_ID", "F_Year", "Product_ID", "Revenue", "Quantity"), row.names = c(NA, 
7L), class = "data.frame") 

Ausgabe

mit
DFO = structure(list(PO_ID = c("P1234", "P1234", "P1234", "P1234", 
"P1234", "P1234", "P2345", "P2345", "P3456", "P4567"), SO_ID = c("S1", 
"S1", "S1", "S2", "S2", "S2", "S3", "S4", "S7", "S10"), F_Year = c(2012, 
2012, 2012, 2013, 2013, 2013, 2011, 2011, 2014, 2015), Product_ID = c("385X", 
"385X", "385X", "450X", "450X", "900X", "3700", "3700", "A11U", 
"2700"), Revenue = c(16.6666666666667, 16.6666666666667, 16.6666666666667, 
35, 35, 35, 100, -50, 50, 100), Quantity = c(1, 1, 1, 10, 10, 
20, 20, -10, 20, 40), Location1 = c("MA", "NY", "WA", "NY", "WA", 
"NY", "IL", "IL", "MN", "CA")), .Names = c("PO_ID", "SO_ID", 
"F_Year", "Product_ID", "Revenue", "Quantity", "Location1"), row.names = c(NA, 
10L), class = "data.frame") 

Hier ist mein Code dplyr

mit Ich bin mit zwei Bibliotheken hier: dplyr und compare

verließ ich bin mit schließen, um neue Einträge aus der Look-Up-Tabelle in DFI hinzufügen. Dann teile ich den Umsatz und die Spalte basierend auf der Anzahl der Zeilen in einer Gruppe. Dies ist, weil ich Inflation von Zahlen verhindern will, wenn sie gruppiert werden.

DF_Generated <- DFI %>% 
    dplyr::left_join(DF_Lookup,by = c("PO_ID", "SO_ID", "F_Year", "Product_ID")) %>% 
    dplyr::group_by(PO_ID, SO_ID, F_Year, Product_ID) %>% 
    dplyr::mutate(Count = n()) %>% 
    dplyr::ungroup()%>% 
    dplyr::mutate(Revenue = Revenue.y/Count, Quantity = Quantity.y/Count) %>% 
    dplyr::select(PO_ID:Product_ID,Location1,Revenue,Quantity) 

Hier ist, wie die Ausgangsspiele:

compare(DF_Generated,DFO,allowAll = TRUE) 
TRUE 

ich aufrichtig schätzen würde jede mögliche Hilfe.

+1

Ok. Alles was ich mache ist ein linker Join und dann mutieren Spalten im Ergebnis. Lassen Sie mich dennoch ein paar Zeilen schreiben. Ich habe die Logik hinzugefügt. – watchtower

Antwort

3

Es ist effizienter, einfach Spalten DFI hinzufügen (in einer "update join"), anstatt eine neue Tabelle zu machen:

DFI[DF_Lookup, on=.(PO_ID, SO_ID, F_Year, Product_ID), 
    `:=`(newrev = i.Revenue/.N, newqty = i.Quantity/.N) 
, by=.EACHI] 

    PO_ID SO_ID F_Year Product_ID Revenue Quantity Location1 newrev newqty 
1: P1234 S1 2012  385X  1  1  MA 16.66667  1 
2: P1234 S1 2012  385X  2  2  NY 16.66667  1 
3: P1234 S1 2012  385X  3  3  WA 16.66667  1 
4: P1234 S2 2013  450X  34  8  NY 35.00000  10 
5: P1234 S2 2013  450X  34  8  WA 35.00000  10 
6: P1234 S2 2013  900X  6  6  NY 35.00000  20 
7: P2345 S3 2011  3700  7  7  IL 100.00000  20 
8: P2345 S4 2011  3700  88  8  IL -50.00000 -10 
9: P3456 S7 2014  A11U  9  9  MN 50.00000  20 
10: P4567 S10 2015  2700  100  40  CA 100.00000  40 

Dies ist eine ziemlich natürliche Erweiterung der Q & A in der verknüpften OP.

Die by=.EACHI Gruppen nach jeder Reihe von i in x[i,on=,j]; und .N ist, wie viele Zeilen die Gruppe hat.

Wenn die rev- und qty-Spalten überschrieben werden sollen, verwenden Sie `:=`(Revenue = i.Revenue/.N, Quantity = i.Quantity/.N).

+0

Fantastisch. Vielen Dank. Wie entferne ich alte Einnahmen und Menge? Ich würde mich freuen, wenn Sie dieses Stück auch hinzufügen könnten. – watchtower

+1

@watchtower Sie könnten ihre Namen innerhalb der '\': = \ '()' verwenden und diese Spalten würden überschrieben werden. (Normalerweise zögere ich so zu überschreiben.) – Frank

+0

Danke Frank. Es ist sehr hilfreich. Ich lese einen Thread auf '.EACHI'. Woher weiß ich, was oben in deinem Code gruppiert ist? Wie in, denke ich, es ist 'PO_ID',' SO_ID', 'F_Year',' Product_ID'? Wenn ja, wie ändere ich Ihren Code, um nur 3 der 4 Spalten zu gruppieren, sagen Sie "PO_ID", "SO_ID", "F_Year"? Ich weiß, das ist eine andere Frage, und ich kann einen neuen Thread dafür erstellen. Lass es mich wissen, bitte. – watchtower

Verwandte Themen