2017-11-21 2 views
1

Ich habe einen Datenrahmen einen Satzes von Bedingungen, zum Beispiel der Anzeige:Spiel mit mehreren Kriterien ohne Schlaufe in R

B = data.frame(col1 = 1:10, col2 = 11:20) 

zum Beispiel die erste Zeile, so dass, wenn spalte1 = 1, Col2 = 11. I auch haben mit den Zahlen einen anderen Datenrahmen, die diese Bedingungen erfüllt sollten, zum Beispiel:

A = data.frame(col1 = c(1:11,1:11), col2 = c(11:21,11:21), col3 = 101:122) 

ich möchte die Summe der Werte in col3 in Matrix A für alle Zeilen, die Fleisch die Bedingungen in B. zurückzukehren für B. die erste Zeile in B verwenden Wert ist:

sum(A$col3[which(A$col1 == B$col1[1] & A$col2 == B$col2[1])]) 
#[1] 213 

, dass die Summe der Einträge in col3 in der 1. und der 12. Zeile von A ist. Ich muss einen Vektor mit all diesen Summen für alle Zeilen der Matrix A finden. Ich weiß, wie man das mit einer Schleife macht, aber in meinen Datenmatrizen sind A und B sehr groß und haben viele Bedingungen, also habe ich mich gefragt, ob es einen Weg gibt, dasselbe ohne die Schleife zu machen. Vielen Dank.

+1

Ich habe Ihren ursprünglichen Beitrag ein wenig bearbeitet, weil das, was Sie "Matrix" nannten, ist eigentlich "Datenrahmen" in R. – www

Antwort

4

Lösung in der Basis R

# Sum identical rows 
A.summed <- aggregate(col3 ~ col1 + col2, data = A, sum); 

# Select col1 col2 combinations that are also present in B 
A.summed.sub <- subset(A.summed, paste(col1, col2) %in% paste(B$col1, B$col2)); 
# col1 col2 col3 
#1  1 11 213 
#2  2 12 215 
#3  3 13 217 
#4  4 14 219 
#5  5 15 221 
#6  6 16 223 
#7  7 17 225 
#8  8 18 227 
#9  9 19 229 
#10 10 20 231 

Oder das gleiche wie ein Einzeiler

A.summed.sub <- subset(aggregate(col3 ~ col1 + col2, data = A, sum), paste(col1, col2) %in% paste(B$col1, B$col2)); 

# Add summed col3 to dataframe B by matching col1 col2 combinations 
B$col3 <- A.summed[match(paste(B$col1, B$col2), paste(A.summed$col1, A.summed$col2)), "col3"]; 
B; 
# col1 col2 col3 
#1  1 11 213 
#2  2 12 215 
#3  3 13 217 
#4  4 14 219 
#5  5 15 221 
#6  6 16 223 
#7  7 17 225 
#8  8 18 227 
#9  9 19 229 
#10 10 20 231 
+0

Dies ist eine große einfache Lösung. Gibt es eine Möglichkeit, die Matrix "B" zu füllen, indem man eine Spalte ("col3") hinzufügt, anstatt eine neue Matrix zu erstellen, so dass die nicht übereinstimmenden Zeilen in B eine 0 erhalten? – Andrew

+1

Nicht ganz sicher, was du meinst. Bitte werfen Sie einen Blick auf meine überarbeitete Lösung. –

3

Eine Lösung mit dplyr. A2 ist die endgültige Ausgabe. Die Idee ist, den Wert in col1 und col2 zu gruppieren und die Summe für col3 zu berechnen. semi_join ist das Filtern des Datenrahmens durch Übereinstimmen von Werten basierend auf col1 und col2 in B.

library(dplyr) 

A2 <- A %>% 
    group_by(col1, col2) %>% 
    summarise(col3 = sum(col3)) %>% 
    semi_join(B, by = c("col1", "col2")) %>% 
    ungroup() 
A2 
# # A tibble: 10 x 3 
#  col1 col2 col3 
# <int> <int> <int> 
# 1  1 11 213 
# 2  2 12 215 
# 3  3 13 217 
# 4  4 14 219 
# 5  5 15 221 
# 6  6 16 223 
# 7  7 17 225 
# 8  8 18 227 
# 9  9 19 229 
# 10 10 20 231 
3

Wir können ein on mit beitreten tun data.table

library(data.table(
setDT(A)[B, .(col3 = sum(col3)), on = .(col1, col2), by = .EACHI] 
# col1 col2 col3 
# 1: 1 11 213 
# 2: 2 12 215 
# 3: 3 13 217 
# 4: 4 14 219 
# 5: 5 15 221 
# 6: 6 16 223 
# 7: 7 17 225 
# 8: 8 18 227 
# 9: 9 19 229 
#10: 10 20 231