Próbuję użyć, grep
aby sprawdzić, czy wektor ciągów jest obecny w innym wektorze, czy nie, i wyprowadzić wartości, które są obecne (pasujące wzorce).
Mam taką ramkę danych:
FirstName Letter
Alex A1
Alex A6
Alex A7
Bob A1
Chris A9
Chris A6
Mam wektor ciągów wzory można znaleźć w kolumnach „litera”, na przykład: c("A1", "A9", "A6")
.
Chciałbym sprawdzić, czy którykolwiek z ciągów w wektorze wzorcowym jest obecny w kolumnie „Letter”. Jeśli tak, chciałbym uzyskać unikalne wartości.
Problem w tym, że nie wiem, jak używać grep
wielu wzorów. Próbowałem:
matches <- unique (
grep("A1| A9 | A6", myfile$Letter, value=TRUE, fixed=TRUE)
)
Ale daje mi 0 dopasowań, co nie jest prawdą, jakieś sugestie?
fixed=TRUE
ponieważ wzorzec jest prawdziwym wyrażeniem regularnym.match
lub%in%
nawet==
jest jedynym prawidłowym sposobem porównywania dokładnych dopasowań. regex jest bardzo niebezpieczne w przypadku takiego zadania i może prowadzić do nieoczekiwanych wyników.Odpowiedzi:
Oprócz komentarza @Marka dotyczącego nieuwzględniania
fixed==TRUE
, w wyrażeniu regularnym nie musisz też mieć spacji. Tak powinno być"A1|A9|A6"
.Wspomniałeś również, że jest wiele wzorów. Zakładając, że są w wektorze
toMatch <- c("A1", "A9", "A6")
Następnie możesz bezpośrednio utworzyć wyrażenie regularne za pomocą
paste
icollapse = "|"
.matches <- unique (grep(paste(toMatch,collapse="|"), myfile$Letter, value=TRUE))
źródło
toMatch %in% myfile$Letter
?Dobre odpowiedzi, ale nie zapomnij o
filter()
dplyr:patterns <- c("A1", "A9", "A6") >your_df FirstName Letter 1 Alex A1 2 Alex A6 3 Alex A7 4 Bob A1 5 Chris A9 6 Chris A6 result <- filter(your_df, grepl(paste(patterns, collapse="|"), Letter)) >result FirstName Letter 1 Alex A1 2 Alex A6 3 Bob A1 4 Chris A9 5 Chris A6
źródło
grepl
działa z jednym wzorcem na raz (potrzebujemy wektora o długości 1), mamy 3 wzorce (wektor o długości 3), więc możemy je połączyć z jednym używając przyjaznego dla grepl separatora -|
spróbuj szczęścia z innymi :))|(
do odrębnych wzorców może uczynić to bardziej wytrzymałe:paste0("(", paste(patterns, collapse=")|("),")")
. Niestety staje się też nieco mniej elegancki. Powoduje to wzór(A1)|(A9)|(A6)
.To powinno działać:
grep(pattern = 'A1|A9|A6', x = myfile$Letter)
Lub jeszcze prościej:
library(data.table) myfile$Letter %like% 'A1|A9|A6'
źródło
%like%
nie znajduje się w podstawowym R, więc powinieneś wspomnieć, jakie pakiety są potrzebne, aby go użyć.%like%
jest częściądata.table
pakietu. Podobne wdata.table
tolike(...)
,%ilike%
i%flike%
.Na podstawie postu Briana Digga, oto dwie pomocne funkcje do filtrowania list:
#Returns all items in a list that are not contained in toMatch #toMatch can be a single item or a list of items exclude <- function (theList, toMatch){ return(setdiff(theList,include(theList,toMatch))) } #Returns all items in a list that ARE contained in toMatch #toMatch can be a single item or a list of items include <- function (theList, toMatch){ matches <- unique (grep(paste(toMatch,collapse="|"), theList, value=TRUE)) return(matches) }
źródło
Czy próbowałeś już funkcji
match()
orcharmatch()
?Przykładowe zastosowanie:
match(c("A1", "A9", "A6"), myfile$Letter)
źródło
match
, że nie używa on wzorców, ale oczekuje dokładnego dopasowania.Nie jestem pewien, czy ta odpowiedź już się pojawiła ...
W przypadku konkretnego wzorca w pytaniu możesz to zrobić za pomocą jednego
grep()
połączenia,grep("A[169]", myfile$Letter)
źródło
Aby dodać do odpowiedzi Briana Diggsa.
inny sposób użycia grepl zwróci ramkę danych zawierającą wszystkie twoje wartości.
toMatch <- myfile$Letter matches <- myfile[grepl(paste(toMatch, collapse="|"), myfile$Letter), ] matches Letter Firstname 1 A1 Alex 2 A6 Alex 4 A1 Bob 5 A9 Chris 6 A6 Chris
Może trochę czystszy ... może?
źródło
Usuń przestrzenie. Więc zrób:
matches <- unique(grep("A1|A9|A6", myfile$Letter, value=TRUE, fixed=TRUE))
źródło
Używając
sapply
patterns <- c("A1", "A9", "A6") df <- data.frame(name=c("A","Ale","Al","lex","x"),Letters=c("A1","A2","A9","A1","A9")) name Letters 1 A A1 2 Ale A2 3 Al A9 4 lex A1 5 x A9 df[unlist(sapply(patterns, grep, df$Letters, USE.NAMES = F)), ] name Letters 1 A A1 4 lex A1 3 Al A9 5 x A9
źródło
Proponuję napisać mały skrypt i przeprowadzić wiele wyszukiwań z Grepem. Nigdy nie znalazłem sposobu na wyszukiwanie wielu wzorów i wierz mi, szukałem!
Podobnie jak plik powłoki, z osadzonym ciągiem znaków:
#!/bin/bash grep *A6* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6"; grep *A7* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6"; grep *A8* "Alex A1 Alex A6 Alex A7 Bob A1 Chris A9 Chris A6";
Następnie uruchom, wpisując myshell.sh.
Jeśli chcesz móc przekazać łańcuch w wierszu poleceń, zrób to w ten sposób, z argumentem powłoki - to jest notacja bash btw:
#!/bin/bash $stingtomatch = "${1}"; grep *A6* "${stingtomatch}"; grep *A7* "${stingtomatch}"; grep *A8* "${stingtomatch}";
I tak dalej.
Jeśli jest wiele wzorców do dopasowania, możesz umieścić je w pętli for.
źródło