Filtern Sie mehrere Werte in einer Zeichenfolgenspalte in dplyr

72

Ich habe eine data.framemit Zeichendaten in einer der Spalten. Ich möchte mehrere Optionen in data.framederselben Spalte filtern . Gibt es eine einfache Möglichkeit, dies zu tun, die mir fehlt?

Beispiel: data.frame name =dat

days      name
88        Lynn
11          Tom
2           Chris
5           Lisa
22        Kyla
1          Tom
222      Lynn
2         Lynn

Ich möchte herausfiltern Tomund Lynnzum Beispiel.
Wenn ich es tue:

target <- c("Tom", "Lynn")
filt <- filter(dat, name == target)

Ich erhalte diesen Fehler:

longer object length is not a multiple of shorter object length
Tom O.
quelle

Antworten:

199

Sie benötigen %in%anstelle von ==:

library(dplyr)
target <- c("Tom", "Lynn")
filter(dat, name %in% target)  # equivalently, dat %>% filter(name %in% target)

Produziert

  days name
1   88 Lynn
2   11  Tom
3    1  Tom
4  222 Lynn
5    2 Lynn

Um zu verstehen, warum, überlegen Sie, was hier passiert:

dat$name == target
# [1] FALSE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE

Grundsätzlich recyceln wir den targetVektor mit zwei Längen viermal, um ihn an die Länge von anzupassen dat$name. Mit anderen Worten, wir machen:

 Lynn == Tom
  Tom == Lynn
Chris == Tom
 Lisa == Lynn
 ... continue repeating Tom and Lynn until end of data frame

In diesem Fall wird kein Fehler angezeigt, da ich vermute, dass Ihr Datenrahmen tatsächlich eine andere Anzahl von Zeilen enthält, die kein Recycling zulassen, die von Ihnen bereitgestellte Stichprobe jedoch (8 Zeilen). Wenn die Stichprobe eine ungerade Anzahl von Zeilen gehabt hätte, hätte ich den gleichen Fehler wie Sie erhalten. Aber selbst wenn das Recycling funktioniert, ist dies eindeutig nicht das, was Sie wollen. Grundsätzlich ist die Aussage dat$name == targetgleichbedeutend mit:

Rückgabe TRUEfür jeden ungeraden Wert, der gleich "Tom" ist, oder für jeden geraden Wert, der gleich "Lynn" ist.

Es kommt also vor, dass der letzte Wert in Ihrem Beispieldatenrahmen gerade und gleich "Lynn" ist, daher der TRUEobige.

Im Gegensatz dazu dat$name %in% targetsagt:

dat$nameÜberprüfen Sie für jeden Wert in , ob er in vorhanden ist target.

Sehr verschieden. Hier ist das Ergebnis:

[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE

Beachten Sie, dass Ihr Problem nichts mit dplyrdem Missbrauch von zu tun hat ==.

BrodieG
quelle
Danke für die Erklärung Brodie! Schätzen Sie das wirklich, Kliniker, der versucht, R herauszufinden!
Tom O
@BrodieG und könnten Sie Ziel mit Muster machen, nicht volle Zeichenfolge?
Manabou11
Nicht mit %in%, aber Sie können dort grepl("T[oi]m|lynne?", name)jedes gewünschte Muster verwenden.
BrodieG
11

Dies kann mit dem in CRAN verfügbaren dplyr-Paket erreicht werden. Der einfache Weg, dies zu erreichen:

  1. dplyrPaket installieren .
  2. Führen Sie den folgenden Code aus
library(dplyr) 

df<- select(filter(dat,name=='tom'| name=='Lynn'), c('days','name))

Erläuterung:

Sobald wir dplyr heruntergeladen haben, erstellen wir einen neuen Datenrahmen mit zwei verschiedenen Funktionen aus diesem Paket:

Filter: Das erste Argument ist der Datenrahmen. Das zweite Argument ist die Bedingung, unter der wir wollen, dass es untergeordnet wird. Das Ergebnis ist der gesamte Datenrahmen mit nur den gewünschten Zeilen. Wählen Sie: Das erste Argument ist der Datenrahmen. Das zweite Argument sind die Namen der Spalten, aus denen wir auswählen möchten. Wir müssen nicht die Funktion names () verwenden und wir müssen nicht einmal Anführungszeichen verwenden. Wir listen die Spaltennamen einfach als Objekte auf.

AutomationNerd
quelle
10

Verwenden des basePakets:

df <- data.frame(days = c(88, 11, 2, 5, 22, 1, 222, 2), name = c("Lynn", "Tom", "Chris", "Lisa", "Kyla", "Tom", "Lynn", "Lynn"))

# Three lines
target <- c("Tom", "Lynn")
index <- df$name %in% target
df[index, ]

# One line
df[df$name %in% c("Tom", "Lynn"), ] 

Ausgabe:

  days name
1   88 Lynn
2   11  Tom
6    1  Tom
7  222 Lynn
8    2 Lynn

Verwenden von sqldf:

library(sqldf)
# Two alternatives:
sqldf('SELECT *
      FROM df 
      WHERE name = "Tom" OR name = "Lynn"')
sqldf('SELECT *
      FROM df 
      WHERE name IN ("Tom", "Lynn")')
mpalanco
quelle
1
 by_type_year_tag_filtered <- by_type_year_tag %>%
      dplyr:: filter(tag_name %in% c("dplyr", "ggplot2"))
Hanif
quelle
2
Dieser Code bietet möglicherweise eine Lösung für das Problem. Es wird jedoch dringend empfohlen, einen zusätzlichen Kontext anzugeben, in dem erläutert wird, warum und / oder wie dieser Code die Frage beantwortet. Nur-Code-Antworten werden auf lange Sicht normalerweise unbrauchbar, da zukünftige Betrachter mit ähnlichen Problemen die Gründe für die Lösung nicht verstehen können.
Palasн