2016-08-03 20 views
1

Sagen, ich habe zwei Datenrahmen wie folgt aus:R: zwei Datenrahmen zusammenführen, wenn eine von zwei Kriterien entspricht

n = c(2, 3, 5, 5, 6, 7) 
s = c("aa", "bb", "cc", "dd", "ee", "ff") 
b = c(2, 4, 5, 4, 3, 2) 
df = data.frame(n, s, b) 
# n s b 
#1 2 aa 2 
#2 3 bb 4 
#3 5 cc 5 
#4 5 dd 4 
#5 6 ee 3 
#6 7 ff 2 

n2 = c(5, 6, 7, 6) 
s2 = c("aa", "bb", "cc", "ll") 
b2 = c("hh", "nn", "ff", "dd") 
df2 = data.frame(n2, s2, b2) 

# n2 s2 b2 
#1 5 aa hh 
#2 6 bb nn 
#3 7 cc ff 
#4 6 ll dd 

Ich möchte, dass sie fusionieren folgendes Ergebnis zu erreichen:

#n s b n2 s2 b2 
#2 aa 2 5 aa hh 
#3 bb 4 6 bb nn 
#5 cc 5 7 cc ff 
#5 dd 4 6 ll dd 

Grundsätzlich , was ich erreichen möchte, besteht darin, die beiden Datenrahmen zusammenzuführen, wenn die Werte in s der ersten Daten in den Spalten s2 oder b2 von data2 gefunden werden.

Ich weiß, dass die Zusammenführung funktionieren kann, wenn ich die zwei Spalten von jedem Datenrahmen angeben, aber ich bin nicht sicher, wie die OR-Bedingung in der Zusammenführungsfunktion HINZUFÜGEN. Oder wie Sie dieses Ziel mit anderen Befehlen aus Paketen wie dpylr erreichen.

Um zu klären, wird es auch eine Situation geben, wo s2 und b2 Übereinstimmungen mit s Spalte in der gleichen Zeile haben. Wenn dies der Fall ist, füge sie einfach einmal zusammen.

Antwort

2

A coupld von Problemen: 1) Sie ein paar Datenrahmen mit Faktoren aufgebaut haben, die hat eine Tendenz, Matching und Indizierung zu vermasseln, also habe ich stringsAsFactors = FALSE in den Datenframeaufrufen verwendet. 2) Sie haben eine unklare Situation ohne festgelegte Auflösung, wenn beide s2 und b2 haben in der Kurve s Spalte (wie in Ihrem Beispiel auftritt):

> df2[c("s")] <- list(c(df$s[pmax(match(df2$s2 , df$s), match(df2$b2, df$s),na.rm=TRUE)])) 
> df2 
    n2 s2 b2 s 
1 5 aa hh aa 
2 6 bb nn bb 
3 7 cc ff ff 
4 6 ll dd dd 
> df2[c("s")] <- list(c(df$s[pmin(match(df2$s2 , df$s), match(df2$b2, df$s),na.rm=TRUE)])) 
> df2 
    n2 s2 b2 s 
1 5 aa hh aa 
2 6 bb nn bb 
3 7 cc ff cc 
4 6 ll dd dd 

Sobald Sie die Mehrdeutigkeit Ihre satiusfaction lösen benutzen Sie einfach die gleiche Verfahren zum extrahieren und die "B" s entsprechen:

> df2[c("b")] <- list(c(df$b[pmin(match(df2$s2 , df$s), match(df2$b2, df$s),na.rm=TRUE)])) 
> df2 
    n2 s2 b2 s b 
1 5 aa hh aa 2 
2 6 bb nn bb 4 
3 7 cc ff cc 5 
4 6 ll dd dd 4 

Modifizierte DFs:

> dput(df) 
structure(list(n = c(2, 3, 5, 5, 6, 7), s = c("aa", "bb", "cc", 
"dd", "ee", "ff"), b = c(2, 4, 5, 4, 3, 2)), .Names = c("n", 
"s", "b"), row.names = c(NA, -6L), class = "data.frame") 
> dput(df2) 
structure(list(n2 = c(5, 6, 7, 6), s2 = c("aa", "bb", "cc", "ll" 
), b2 = c("hh", "nn", "ff", "dd"), s = c("aa", "bb", "cc", "dd" 
), b = c(2, 4, 5, 4)), row.names = c(NA, -4L), .Names = c("n2", 
"s2", "b2", "s", "b"), class = "data.frame") 

One step Lösung:

> df2[c("s", "c")] <- df[pmin(match(df2$s2 , df$s), match(df2$b2, df$s),na.rm=TRUE), c("s", "b")] 
> df2 
    n2 s2 b2 s c 
1 5 aa hh aa 2 
2 6 bb nn bb 4 
3 7 cc ff cc 5 
4 6 ll dd dd 4 
+0

Es könnte funktionieren, aber beide der tatsächlichen zwei Datenrahmen habe ich über 30 Spalten. Wenn ich jeweils eine Spalte hinzufüge, dauert es zu lange. Zur Klarstellung wird es auch keine Situation geben, in der s2 und b2 Übereinstimmungen mit der Spalte s in derselben Zeile haben. – lll

+0

Ich poste ein kompaktes für das tut beide Spalten in einem Schritt: –

+0

Danke für die Überarbeitung der Lösungen. Aber was ich meine ist, dass in den tatsächlichen Daten jede Daten mehr als 30 Spalten zusammen haben. Und 2 Spalten sind das "s" und "c" wie im ersten Datenrahmen. Ich möchte diese Spalten als Auswahlkriterien verwenden, ohne andere Spalten (die anderen über 20 Spalten) zu verlieren, die ich nicht hochgeladen habe.Ist das in dieser Lösung, fügt es effektiv zwei weitere Spalten zu df2 hinzu, aber was ich wirklich will, ist zusätzlich zu den zwei Spalten, das Ergebnis von mehr als 20 Spalten. – lll

1

Wenn Sie mit SQL vertraut sind, könnten Sie verwenden:

library(sqldf) 
res <- sqldf("SELECT l.*, r.* 
       FROM df as l 
       INNER JOIN df2 as r 
       on l.s = r.s2 OR l.s = r.b2") 

res 
    n s b n2 s2 b2 
1 2 aa 2 5 aa hh 
2 3 bb 4 6 bb nn 
3 5 cc 5 7 cc ff 
4 5 dd 4 6 ll dd 
5 7 ff 2 7 cc ff 

Daten:

df<-structure(list(n = c(2, 3, 5, 5, 6, 7), s = structure(1:6, .Label = c("aa", 
"bb", "cc", "dd", "ee", "ff"), class = "factor"), b = c(2, 4, 
5, 4, 3, 2)), .Names = c("n", "s", "b"), row.names = c(NA, -6L 
), class = "data.frame") 

df2<-structure(list(n2 = c(5, 6, 7, 6), s2 = structure(1:4, .Label = c("aa", 
"bb", "cc", "ll"), class = "factor"), b2 = structure(c(3L, 4L, 
2L, 1L), .Label = c("dd", "ff", "hh", "nn"), class = "factor")), .Names = c("n2", 
"s2", "b2"), row.names = c(NA, -4L), class = "data.frame") 
+0

Ich habe versucht, aber es sagt, Fehler in der Aussage: keine solche Tabelle: DF2, während DF2 in der Arbeitsumgebung gespeichert – lll

+0

I reran und es funktioniert für mich. Ich habe die Daten, die ich verwendet habe, gepostet (die genauso sein sollten wie deine). –

+0

es läuft immer noch nicht auf meinen eigenen Daten, während es auf die Beispieldaten funktioniert, die ich gepostet habe (ich habe das auch gerade ausgeführt). Gibt es eine andere Möglichkeit, die beiden zusammenzuführen? – lll

0

Ein Basisansatz ist das Verbinden zweier Merges. Sie müssen die entsprechenden Join-Schlüssel in df2 neu erstellen, um die Frames effektiv zu verketten. Auch # 5 Reihe entsteht nicht in der gewünschten Ergebnissen:

t1 <- merge(df, df2, by.x=c("s"), by.y=c("s2")) 
t1$s2 <- t1$s 

t2 <- merge(df, df2, by.x=c("s"), by.y=c("b2")) 
t2$b2 <- t2$s 

finaldf <- rbind(t1, t2) 

# s n b n2 b2 s2 
# 1 aa 2 2 5 hh aa 
# 2 bb 3 4 6 nn bb 
# 3 cc 5 5 7 ff cc 
# 4 dd 5 4 6 dd ll 
# 5 ff 7 2 7 ff cc 
Verwandte Themen