2016-04-22 17 views
2

Ich habe folgende Daten:Merging und Zusammenfassung zwei Datenrahmen

a <- data.frame(ID=c("A","B","Z","H"), a=c(0,1,2,45), b=c(3,4,5,22), c=c(6,7,8,3)) 
> a 
    ID a b c 
1 A 0 3 6 
2 B 1 4 7 
3 Z 2 5 8 
4 H 45 22 3 

b <- data.frame(ID=c("A","B","E","W","Z","H"), a=c(9,10,11,39,5,0), b=c(4,2,7,54,12,34), c=c(12,0,34,23,13,14)) 

> b 
    ID a b c 
1: A 9 4 12 
2: B 10 2 0 
3: E 11 7 34 
4: W 39 54 23 
5: Z 5 12 13 
6: H 0 34 14 

Ich mag beiden Datenrahmen verschmelzen, nur Reihen von data.frame einer zu halten und die gleichen Spalten zusammenfassen, so dass am Ende bekomme ich:

> z 
    ID a b c 
1 A 9 7 18 
2 B 11 6 7 
3 Z 7 17 21 
4 H 45 56 17 

Bisher habe ich versucht, die folgenden:

merge(a,b,by="ID",all.x=T,all.y=F) 
> merge(a,b,by="ID",all.x=T,all.y=F) 
    ID a.x b.x c.x a.y b.y c.y 
1 A 0 3 6 9 4 12 
2 B 1 4 7 10 2 0 
3 H 45 22 3 0 34 14 
4 Z 2 5 8 5 12 13 

> join(a,b,type="left",by="ID") 
    ID a b c a b c 
1 A 0 3 6 9 4 12 
2 B 1 4 7 10 2 0 
3 Z 2 5 8 5 12 13 
4 H 45 22 3 0 34 14 

ich nicht die Spalten zusammenfassen verwalten können.

Mein Dataframe ist ziemlich groß, wenn die Lösung Dinge beschleunigen kann, die sogar besser wären.

Antwort

1

Wenn Ihr data.frame sehr groß ist, dann können Sie diese Option in Betracht ziehen:

library(data.table) 

## convert data.frame to data.table 
setDT(a) 

## convert data.frame to data.table 
setDT(b) 

## merge the two data.tables 
c <- merge(a,b,by='ID') 

## extract names of all columns except the first one i.e. ID 
col_names <- colnames(a)[-1] 

## query building 
col_1 <- paste0(col_names,'.x') 

col_2 <- paste0(col_names,'.y') 

cols <- paste(col_1,col_2,sep=',') 

cols_2 <- paste0(col_names," = sum(",cols,")") 

cols_3 <- paste(cols_2,collapse=',') 

query <- paste0("z <- c[,.(",cols_3,"),by=ID]") 

## query execution 
eval(parse(text = query)) 
1

Dies zumindest für Ihr Beispiel funktioniert:

a <- data.frame(ID=c("A","B","Z","H"), a=c(0,1,2,45), b=c(3,4,5,22), c=c(6,7,8,3)) 
b <- data.frame(ID=c("A","B","E","W","Z","H"), a=c(9,10,11,39,5,0), b=c(4,2,7,54,12,34), c=c(12,0,34,23,13,14)) 

match_a <- na.omit(match(b$ID, a$ID)) 
match_b <- na.omit(match(a$ID, b$ID)) 

df <- cbind(ID = a$ID[match_a], a[match_a, -1] + b[match_b, -1]) 

Zunächst holen Zeilen aus a in b und umgekehrt übereinstimmt, so können wir sicher sein, dass wir nur die Zeilen, die in beiden Datenrahmen erscheinen (und wir kennen jetzt ihre Reihenindizes in beiden Datenrahmen). Verwenden Sie dann einfach die vektorisierten Zusätze für die übereinstimmenden Zeilen, aber lassen Sie ID aus, da factor nicht summiert werden kann; fügen Sie ID manuell zurück.

0

Sie können nicht beide Datenrahmen direkt hinzufügen, da beide Datenrahmen ungleich groß sind. Um sie gleich groß zu machen, können Sie nach ID s in a suchen, die in b vorhanden sind, und sie dann elementweise hinzufügen.

new <- b[b$ID %in% a$ID, ] 
cbind(ID = a$ID, a[-1] + new[-1]) 

# ID a b c 
#1 A 9 7 18 
#2 B 11 6 7 
#3 Z 7 17 21 
#4 H 45 56 17 
+1

Große, die drei Optionen perfekt funktionieren. – david