2017-02-22 4 views
2

ich einen Datenrahmen haben, die wie folgt aussieht:Filter R Datenrahmen, um nur Reihen mit einem Abstand zwischen zwei Zeichenketten

v1 <- c('abies balsamifera','some trees','pizza','i like tacos','pinus taeda') 
v2 <- c(1,2,3,4,5) 
data <- data.frame(v1,v2) 
       v1 v2 
1 abies balsamifera 1 
2  some trees 2 
3    pizza 3 
4  i like tacos 4 
5  pinus taeda 5 

Ich möchte die Datenrahmen der Teilmenge, nur mit Zeilen, in denen die Zeichenketten in v1 habe zwei Wörter, die durch ein Leerzeichen getrennt sind. Ich möchte Zeilen ausschließen, die nur ein Wort enthalten, oder andere Zeilen, die drei Wörter enthalten. Die sich ergebende Datenrahmen würde wie folgt aussehen:

    v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

Antwort

7

Sie nach einer Zeichenfolge suchen, der aus einem oder mehreren Wortzeichen zusammengesetzt ist, ein Raum, und wieder ein oder mehrere Wortzeichen.

Dies ist ein regulärer Ausdruck, den die obige Aussage beschreibt:

> grepl('^\\w+\\s\\w+$', v1) 
[1] TRUE TRUE FALSE FALSE TRUE 

Sie können Ihren Datenrahmen mit diesem logischen Vektorindex.

3

Eine Alternative zählt die Anzahl der Leerzeichen, so dass mehr als ein benachbarter Platz möglich ist (z. B. ein Dateneingabe-Tippfehler).

data[sapply(gregexpr(" +", data$v1), function(i) sum(i > 0)) == 1, ] 
       v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

gregexpr liest durch einen Zeichenvektor und gibt eine Liste von Vektoren von Positionen compsed, die für jedes Element des Zeichenvektor entsprechen. Nicht-Übereinstimmungen werden angegeben (-1), daher werden alle Werte mit 0 verglichen und dann summiert. Werte mit einer Übereinstimmung (ein einzelner Satz von benachbarten Leerzeichen) geben TRUE zurück. sapply wird verwendet, um die Liste zu lesen und gibt einen Vektor zurück.

1

Hier ist eine Lösung, die strsplit() verwendet. Bitte beachten Sie, dass es wahrscheinlich langsamer ist, da es eine Schleife verwendet.

v1 <- c('abies balsamifera','some trees','pizza','i like tacos','pinus taeda') 
v2 <- c(1,2,3,4,5) 
data <- data.frame(v1,v2) 
colnames(data) <- c("v1", "v2") 

spacer <- function(data){ 
    booleans <- vector() 
    i <- 1 
    while (i <= nrow(data)){ 
     tmp <- strsplit(as.character(data$v1[i]), ' ')[[1]] 
     booleans[i] <- (length(tmp) == 2) 
     i <- i + 1 
    } 
    return(res[(booleans),]) 
} 

data <- spacer(data) 

Ausgang:

    v1 v2 
1 abies balsamifera 1 
2  some trees 2 
5  pinus taeda 5 

Hinweis: Der obige Code bearbeitet wurde aus @MatthewLundberg Lesbarkeit und Funktionalität mit Begrüßungs Empfehlungen zur Verbesserung der

+1

Sie können den Code vereinfachen und besser lesbar machen. Zuerst, statt dieser 'if'-Anweisung, weise einfach direkt zu: 'booleans [i] <- length (tmp) == 2'. Zweitens gibt es keinen Grund, den "booleschen" Vektor an den Datenrahmen zu binden, sondern einfach "res $" in der letzten 'return' Zeile der Funktion zu entfernen. Dann müssen Sie diese Spalte nicht entfernen, indem Sie 'NULL' zuweisen. Und drittens, als ein separates Problem, können Sie den 'booleschen' Vektor so erstellen, dass er die richtige Länge hat, da Sie wissen, dass er zu' nrow (data) 'Elementen anwachsen wird. –

+0

@MatthewLundberg Danke für die Überprüfung des Codes-- Ich habe diesen Code schnell geschrieben, um eine Antwort zu bekommen (ich benutze SO, um ein besserer Programmierer zu werden), aber ich habe es später angeschaut und viele unnötige Operationen bemerkt. Ich werde deine Empfehlungen verwenden. Ich schätze deine Zeit sehr! –

Verwandte Themen