2012-03-02 14 views
26

In R, grep di solito corrisponde a un vettore di più stringhe rispetto a una regexp.R grep: abbina una stringa a più modelli

D: C'è la possibilità di abbinare una singola stringa a più espressioni regolari? (senza ricorrere a ogni singolo schema regexp)?

Alcuni retroscena:

ho 7000+ parole chiave come indicatori per diverse categorie. Non riesco a cambiare il dizionario delle parole chiave. Il dizionario ha seguente struttura (parole chiave in Col 1, i numeri indicano le categorie in cui queste parole chiave appartengono a):

ab 10 37 41 
abbrach* 38 
abbreche 39 
abbrich* 39 
abend* 37 
abendessen* 60 63 
aber 20 23 45 
abermals 37 

Concatenazione tante le parole chiave con "|" non è un modo fattibile (e non saprei quale delle parole chiave ha generato il successo). Inoltre, solo l'inversione di "schemi" e "stringhe" non funziona, poiché i motivi hanno troncamenti, che non funzionerebbero viceversa.

[related question, altro linguaggio di programmazione]

+2

I come i suggerimenti di Dan, ma con un ampio set di dati potresti riscontrare alcuni problemi di velocità significativi. Se vuoi cercare qualcosa in un dizionario e restituire un valore corrispondente, suggerirei un approccio diverso: spezzando le frasi in vettori di singole parole con strsplit e poi applicando una tabella hash per una rapida ricerca. Sto pensando che potresti voler spezzare la parola chiave e gli indicatori di categoria in due colonne separate nel dizionario. Fornirei assistenza lì, ma solo dopo che sarai più chiaro sul desiderio come risultato finale. –

+0

Concordato sulla ristrutturazione dei dati del dizionario e sull'utilizzo di una tabella hash per la ricerca (in base al risultato desiderato), ma la corrispondenza dovrebbe essere relativamente veloce a seconda del numero di stringhe, anche con un numero elevato di parole chiave. Aggiungerò un rapido punto di riferimento alla mia risposta. – danpelota

+1

Se hai davvero un sacco di parole (tipicamente, tutte le parole in una lingua umana, tutte le parole indicizzate da google, ecc.), puoi usare un [albero dei prefissi] (http: // en. wikipedia.org/wiki/Trie) (a volte viene anche chiamato "trie"). Ma non sono a conoscenza di alcuna implementazione in R. –

risposta

28

Che dire applicando la funzione RegExpr su un vettore di parole chiave?

keywords <- c("dog", "cat", "bird") 

strings <- c("Do you have a dog?", "My cat ate by bird.", "Let's get icecream!") 

sapply(keywords, regexpr, strings, ignore.case=TRUE) 

    dog cat bird 
[1,] 15 -1 -1 
[2,] -1 4 15 
[3,] -1 -1 -1 

    sapply(keywords, regexpr, strings[1], ignore.case=TRUE) 

dog cat bird 
    15 -1 -1 

valori restituiti sono la posizione del primo carattere nella partita, con -1 significato alcuna corrispondenza.

Se la posizione della partita è irrilevante, utilizzare grepl invece:

sapply(keywords, grepl, strings, ignore.case=TRUE) 

     dog cat bird 
[1,] TRUE FALSE FALSE 
[2,] FALSE TRUE TRUE 
[3,] FALSE FALSE FALSE 

Aggiornamento: Questo viene eseguito relativamente rapido sul mio sistema, anche con un gran numero di parole chiave:

# Available on most *nix systems 
words <- scan("/usr/share/dict/words", what="") 
length(words) 
[1] 234936 

system.time(matches <- sapply(words, grepl, strings, ignore.case=TRUE)) 

    user system elapsed 
    7.495 0.155 7.596 

dim(matches) 
[1]  3 234936 
+0

Grazie per la risposta e i vostri commenti! Alla fine, ho fatto un approccio combinato: un trie ha ridotto il set di possibili corrispondenze al ~ 5% delle dimensioni originali, e la funzione sdolcinata ha fatto il grep. –

+0

E poi per vedere quante delle parole chiave corrispondono per frase/stringa, sul frame di dati finale, problema: num.matches <- apply (data.frame (matches), 1, function (z) sum (z == TRUE)) . E per cercare la stringa originale ha, diciamo, 2 corrispondenze, problema: stringhe [num.matches == 2] # Output: [1] "Il mio gatto ha mangiato per uccello". –

+0

Cosa fare se si desidera eseguire una sostituzione, in cui non si leggono solo le parole chiave da cercare, ma anche le loro sostituzioni? – user1603472

2

Per espandere su other answer, per trasformare l'output sapply() in un vettore logico utile è necessario utilizzare ulteriormente un passaggio apply().

keywords <- c("dog", "cat", "bird") 
strings <- c("Do you have a dog?", "My cat ate by bird.", "Let's get icecream!") 
(matches <- sapply(keywords, grepl, strings, ignore.case=TRUE)) 
#  dog cat bird 
# [1,] TRUE FALSE FALSE 
# [2,] FALSE TRUE TRUE 
# [3,] FALSE FALSE FALSE 

sapere quali stringhe contengono qualsiasi delle parole chiave (modelli):

apply(matches, 1, any) 
# [1] TRUE TRUE FALSE 

sapere quali parole chiave (modelli) sono stati abbinati a delle corde in dotazione:

apply(matches, 2, any) 
# dog cat bird 
# TRUE TRUE TRUE