2016-10-24 4 views
1

Ich habe zwei Datenrahmen, SCR und SpecificSpecies. Die Namen der SCR-Artikel enthalten zum Teil die in Specific Species aufgeführten Arten.Effiziente Möglichkeit, über zwei Listen zu iterieren (Nested Loop Alternative)

SpecificSpecies$Species 
S cerevisiae 
Daucus carota 

SCR$MESH_HEADINGS 
tetracycline CMT-3 
zrg17 protein, S cerevisiae 
EP4 glycoprotein, Daucus carota 

Ich versuche Teilmenge von SCR zu erhalten, die nur die Einträge enthalten, die keine passende Spezies nicht haben. Im obigen Fall würde diese Liste nur

sein
tetracycline CMT-3. 

Die Art und Weise habe ich gelernt, dies zu tun, wäre mit verschachtelten Schleifen, jeden Eintrag in SCR zu jedem Eintrag in SpecificSpecies zu vergleichen. Wenn keine Übereinstimmung gefunden wird, hängen die Reihe der SCR in eine neue Tabelle:

For each row in SCR { 
    SpeciesNumber <- 1 
    match <-NULL 
    while ((is.null(match)) & (SpeciesNumber < length(SpecificSpecies$Species))) { 
    if (grepl(SpecificSpecies$Species[SpeciesNumber], SCR[row,]$MESH_HEADING)){ 
    match <- TRUE} 
    SpeciesNumber <- SpeciesNumber + 1} 
    if ((is.null(match) & SpeciesNumber == length(SpecificSpecies$Species)) { 
    speciesNoMatch = rbind(speciesNoMatch, SCR[row])} 
}} 

Aber das ist quälend langsam mit 65.000 Einträgen in SCR und etwa 1500 in SpecificSpecies. Gibt es eine Möglichkeit so zu nisten? Oder eine andere Funktion, die mir hier nicht vertraut ist?

Ich bin sicher, das ist schrecklich Code zu beginnen. Ich bin ein medizinischer Bibliothekar, der R manchmal für die Datenanalyse verwenden muss, daher habe ich sehr begrenzte Programmierkenntnisse, aber normalerweise ist es egal, ob meine Lösungen hässlich oder ineffizient sind, solange sie schließlich funktionieren. Ich weiß, dass es einen besseren Weg geben muss, dies zu tun; verzeih mir, dass ich etwas ignoriere, was wahrscheinlich eine einfache Lösung ist.

Antwort

0

Ich denke !(%in%) den Trick:

SpecificSpecies <- data.frame(
    Species = c("S cerevisiae", "Daucus carota"), 
    stringsAsFactors = FALSE 
) 

SCR <- data.frame(
    MESH_HEADINGS = c("tetracycline CMT-3", "zrg17 protein", "S cerevisiae", 
        "EP4 glycoprotein", "Daucus carota"), 
    stringsAsFactors = FALSE 
) 


SCR[!(SCR$MESH_HEADINGS %in% SpecificSpecies$Species), , drop = FALSE] 
#  MESH_HEADINGS 
# 1 tetracycline CMT-3 
# 2  zrg17 protein 
# 4 EP4 glycoprotein 

Die , , drop = ... kein Tippfehler ist. Die erste , stellt sicher, dass alle Spalten/Variablen zurückgegeben werden. Die zweite , drop = FALSE stellt sicher, dass das zurückgegebene Ergebnis immer noch ein Datenframe ist.

Korrektur

Ok, ich habe Sie suchen mit dem Species-grep nur bemerkt. Der folgende Code sollte funktionieren:

SpecificSpecies <- data.frame(
    Species = c("S cerevisiae", "Daucus carota"), 
    stringsAsFactors = FALSE 
) 

SCR <- data.frame(
    MESH_HEADINGS = c("tetracycline CMT-3", 
        "zrg17 protein, S cerevisiae", 
        "EP4 glycoprotein, Daucus carota"), 
    stringsAsFactors = FALSE 
) 

matching <- lapply(SpecificSpecies$Species, function(x) { 
    grep(x, SCR$MESH_HEADINGS) 
}) 

SCR[-(unlist(matching)), ] 
#  MESH_HEADINGS 
# 1 tetracycline CMT-3 

Die lapply() verwendet eine anonyme Funktion zu identifizieren Muster übereinstimmt. Es durchläuft jede Art und vergleicht sie mit jedem Artikel. Es gibt eine Liste übereinstimmender Indizes zurück.

Die Untergruppe ([]) löscht einfach die übereinstimmenden Indizes (-), nachdem wir zuerst die übereinstimmenden Indizes editiert haben, um sie mit der Teilmengenfunktion kompatibel zu machen.

+0

Nein, ich fürchte nicht. Diese Kommas sind keine Trennzeichen, sie sind Teil der ursprünglichen Zeichenkette. Das heißt, einige der Einträge haben die Form "Protien name, species name". Ich brauche grep oder regex oder etwas ähnliches, um die Matches zu liefern, da die Spezies nur einen Teil des SCR $ MESH_HEADING abdeckt. – NotMyJob

+0

@NotMyJob Ich habe gerade bemerkt, siehe meine Bearbeitung – Phil

+0

Vielen Dank für Ihre Hilfe mit diesem! Zwei Dinge. Zunächst funktioniert Ihr Beispiel für mich, schlägt aber fehl, wenn ich versuche, meine tatsächlichen Daten zu verwenden. Ich bekomme eine Liste von 0 und dann eine leere Tabelle auf der Liste. Irgendeine Idee warum? Zweitens brauche ich den gesamten Datensatz von SCR, wenn ich Teilmenge, nicht nur die MESH_HEADING. Gibt es einen einfachen Weg, um die ganze Reihe zurückzugeben? – NotMyJob

0

Hauptidee:

Dadurch könnte die Schleife auf SpecificSpecies, da sie weniger Reihe hat. Da der SCR-Datenrahmen reduziert wird, rekursiv, sodass die Schleife jedes Mal weniger Daten verarbeitet.

Im Allgemeinen erhöhen die Pakete data.table oder plyr die Leistung. Hier ist die Lösung mit data.table

library(data.table) 
SpecificSpecies <- data.frame(Species = c("S cerevisiae", "Daucus carota"),stringsAsFactors = FALSE) 
SCR <- data.frame(MESH_HEADINGS = c("tetracycline CMT-3", "zrg17 protein, S cerevisiae","EP4 glycoprotein Daucus carota"),stringsAsFactors = FALSE) 

dt_temp <- data.table(SCR) 
for (species in SpecificSpecies$Species) { 
    dt_temp <- dt_temp[!grepl(species,dt_temp$MESH_HEADINGS), ] 
} 
dt_result <- dt_temp 
dt_result 
+0

@NotMyJob funktioniert es so schnell wie Sie möchten? kannst du als gelöst markieren? – timat