2016-07-28 10 views
1

I haben Datenrahmen df1 mit Säulen "Year" und "Agent":Auswählen von Spalten basierend auf Übereinstimmungen/Fuzzy-Übereinstimmungswert von zwei Spalten

df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", "suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent"), row.names = c(NA, -3L), class = "data.frame") 

#df1 
Year         Agent 
1999 abn-amro-nv, suntrust banks, wachovia 
1999     jp morgan, abn-amro-nv 
1998    ba-corp, boston bks, nbd 

Ich habe einen anderen Datenrahmen df2 die 5 Spalten "Rank", "Arrangers", "Share", "Issues" und "Year", wie folgend:

df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", "suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", "Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, -3L)) 

#df2 
Rank Arranger   Share Issues Year 
1  jp morgan  1.2  7  1999 
2  boston-bank  1.8  4  1998 
3  suntrust bk  2.1  3  1999 

ich brauche "Agent" undübereinstimmenvon df1 mit und "Year" von df2 und wählen 3 Spalten aus df2 wie "Rank", "Share", "Issues". Anpassung von "Agent" von df1 mit "Arranger" von df2 wird Fuzzy-Abgleich sein. Weil sie nicht genau gleich sind.

Meine ursprünglichen Datenrahmen sind nur zu Ihrer Information sehr groß.

Im Anschluss ist mein Code:

library(stringdist) 

leadrep <- matrix(ncol=3, nrow=length(df1$Agent)) 

for (i in 1:length(df1$Agent)) { 

    for (j in 1:length(df2$Arrangers)) { 

     if ((ain(df2$Arrangers[j], df1$Agent[[i]], maxDist=0.3, 
     method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){    

     leadrep[i,] <- df2[j, c('Rank', 'Mkt.Share', 'NumberofIssues')] 

     } 

    } 
} 

Im Code leadrep Matrix ist, die ich erstellt. Damit kann ich in der for loop auffüllen. Ich verwendete stringdist Paket und ain Funktion, um Fuzzy-Abgleich zu tun. Und ich habe zwei for loop und if verwendet, um die Strings und das Jahr zu vergleichen.

Der obige Code funktioniert, aber es dauert zu lange, um die Ergebnisse zu erhalten, da meine Datenrahmen groß sind. Ich denke wirklich, dass mein Ansatz oben nicht effizient ist. Es wäre eine große Hilfe, wenn mir jemand eine bessere Alternative zu meinem bestehenden Code bietet.

Vielen Dank für Ihre Hilfe.

+0

Welche Fehler haben Sie bekommen? – shayaa

+0

'Fehler: unerwartet '&' in: " if ((ain (df2 $ Arranger [j], df1 $ Agent [[i]], maxDist = 0.3, method = "jw")) == 'TRUE') & "' Fehler: unerwartet '}' in "}" – Santosh

+0

Diese Frage könnte aufgrund eines einfachen Tippfehlers eines zusätzlichen '('. – shayaa

Antwort

1

Der folgende Ansatz verwendet foreach anstelle von zwei verschachtelten for-Schleifen, die Ihre Berechnung viel schneller auf großen Datenrahmen machen sollte. Einen guten Überblick über das Paket finden Sie unter this. Sie sollten sich auch die Vignetten ansehen.

library(foreach) 
library(stringdist) 

match.cond <- function(ij, df1, df2) {         ## 1. 
    i = floor((ij-1)/nrow(df2)) + 1 
    j = ij - (i-1) * nrow(df2) 
    if ((ain(df2$Arranger[j], df1$Agent[[i]], maxDist=0.3, 
     method="jw")) == 'TRUE' & (df1$Year[i] == df2$Year[j])){ 
    return(df2[j, c('Rank', 'Share', 'Issues')]) 
    } 
} 

leadrep <- foreach(ij = 1:(nrow(df1)*nrow(df2)), .combine=rbind) %do% ## 2. 
    match.cond(ij, df1, df2) 

Hinweise:

  1. match.cond ist Ihr Spiel Zustand in einen Kernel Funktion gekapselt, die vektorisiert werden durch foreach über alle Paarungen von Zeilen aus df1 und df2. Seine Eingaben sind ij, was ein Index für die Paarungen und die zwei Datenrahmen ist. Innerhalb match.cond:
    • ij zu dem Zeilenindizes umgewandelt wird i für df1 und j für df2
    • ist Ihre Bedingung ausgewertet, und wenn die Bedingung erfüllt ist,
    • Die Spalten von df2 für das angepasste Zeile zurückgegeben .
  2. Dies ist der foreach Aufruf.
    • Wir Schleife über die Indizes von ij1 zu nrow(df1)*nrow(df2), die alle Paarungen von Zeilen aus df1 und df2 und %do% die match.cond Funktion aufführt. Beachten Sie, dass dies alles eine Zeile ist.
    • Das .combine=rbind Argument besagt, dass wir alle Ergebnisse von match.cond sammeln und sie als Zeilen binden möchten.
    • Diese den Datenrahmen gibt leadrep

ich auf Ihre Daten getestet habe, die ich dput haben:

df1 <- structure(list(Year = c(1999, 1999, 1998), Agent = list(c("abn-amro-nv", 
"suntrust banks", "wachovia"), c("jp morgan", "abn-amro-nv"), 
c("ba-corp", "boston bks", "nbd"))), .Names = c("Year", "Agent" 
), row.names = c(NA, -3L), class = "data.frame") 

df2 <- structure(list(Rank = 1:3, Arranger = c("jp morgan", "boston-bank", 
"suntrust bk"), Share = c(1.2, 1.8, 2.1), Issues = c(7L, 4L, 
3L), Year = c(1999L, 1998L, 1999L)), .Names = c("Rank", "Arranger", 
"Share", "Issues", "Year"), class = "data.frame", row.names = c(NA, 
-3L)) 

, die mir das gewünschte Ergebnis liefert:

print(leadrep) 
## Rank Share Issues 
##3  3 2.1  3 
##2  1 1.2  7 
##21 2 1.8  4 

Hoffe das hilft.

+0

Danke für Ihre Lösung. Mein aktueller Code benötigt zu viel Zeit. Ihr Ansatz hilft mir, die Rechenzeit zu reduzieren. Nochmals vielen Dank. – Santosh

+0

Eigentlich hatte ich einen kleinen Fehler in meinem ursprünglichen Post. Bei der Berechnung von 'i' und' j' sollte ich 'now (df2)' anstelle von 'now (df1)' verwenden. Dies ist wichtig, wenn sie nicht gleich sind, was bei den Testdaten nicht der Fall war. Ich habe die Änderungen bereits vorgenommen. – aichao

Verwandte Themen