2015-02-20 17 views
6

Vorrei raggruppare gli elenchi estratti da tabelle HTML. Di seguito viene presentato un esempio di lavoro minimo. L'esempio dipende dal pacchetto stringr in R. Il primo esempio mostra il comportamento desiderato.Estrarre l'ultimo numero a 4 cifre da una serie in R utilizzando stringr

years <- c("2005-", "2003-") 
unlist(str_extract_all(years,"[[:digit:]]{4}")) 

[1] "2005" "2003" 

L'esempio seguente produce un risultato indesiderabile quando si tenta di abbinare l'ultimo numero di 4 cifre in una serie di altri numeri.

years1 <- c("2005-", "2003-", "1984-1992, 1996-") 
unlist(str_extract_all(years1,"[[:digit:]]{4}$")) 

character(0) 

quanto ho capito la documentazione, devo includere $ alla fine del modello al fine di richiedere la partita alla fine della stringa. Preferirei abbinare dal secondo esempio i numeri "2005", "2003" e "1996".

+0

'substr (years1,1,4)' fornisce un elenco di "2005" "2003" "1984" dove vorrei ottenere "2005", "2003" e "1996" Che ne dici di – Daniel

+0

'sub ('. * (\\ d {4}). *', '\\ 1', years1)'? – jbaums

+0

@jbaums, che funziona sicuramente, potresti fornire una risorsa/spiegazione per la tua soluzione? – Daniel

risposta

7

Il pacchetto stringi ha comode funzioni che operano su parti specifiche di una stringa. Quindi puoi trovare l'ultima occorrenza di quattro cifre consecutive con il seguente.

library(stringi) 

x <- c("2005-", "2003-", "1984-1992, 1996-") 

stri_extract_last_regex(x, "\\d{4}") 
# [1] "2005" "2003" "1996" 

Altri modi per ottenere lo stesso risultato sono

stri_sub(x, stri_locate_last_regex(x, "\\d{4}")) 
# [1] "2005" "2003" "1996" 

## or, since these count as words 
stri_extract_last_words(x) 
# [1] "2005" "2003" "1996" 

## or if you prefer a matrix result 
stri_match_last_regex(x, "\\d{4}") 
#  [,1] 
# [1,] "2005" 
# [2,] "2003" 
# [3,] "1996" 
+1

Spesso mi trovo a guardare i tuoi post, pensando _ Ho davvero bisogno di familiarizzare con quel pacchetto _... :) – jbaums

+1

Grazie per la risposta completa e l'esposizione a 'stringi' – Daniel

7

È possibile utilizzare base di R sub per questo abbastanza facilmente:

sub('.*(\\d{4}).*', '\\1', years1) 

## [1] "2005" "2003" "1996" 

Il modello da abbinare qui è .* (zero o più di qualsiasi carattere) seguito da \\d{4} (quattro numeri consecutivi, che catturiamo racchiudendoli tra parentesi), seguiti da zero o più caratteri.

sub sostituisce il modello abbinato con il valore nel secondo argomento. In questo caso, \\1 indica che vogliamo sostituire l'intero modello abbinato con la prima sottostringa acquisita (vale a dire i quattro numeri consecutivi).

Qui regex è avido, quindi ignorerà le partite iniziali di \\d{4}, consumandole con .*. Viene catturata solo l'ultima sequenza di quattro numeri consecutivi.

+0

Questa è una soluzione molto utile, mi sono imbattuto di fronte con problemi simili. Quanto sarebbe difficile cambiare l'espressione in modo che corrisponda a * prima * quattro cifre anziché le ultime? – Konrad

+1

@Konrad: è possibile farlo con 'sub ('\\ D * (\\ d {4}). *', '\\ 1', years1)', dove '\\ D *' significa zero o più personaggi che non sono numeri. – jbaums

2

La fine della stringa $ anchor asserisce la posizione alla fine della stringa.

Precisando, corrispondono esattamente quattro cifre alla fine della stringa. Sfortunatamente, ciò che succede è che le cifre cercano di ottenere una corrispondenza, quindi il motore regex avanza cercando di affermare quella posizione e fallisce perché non in questa posizione e indietro di seguito per cercare di abbinarli.

Per risolvere questo problema, è possibile utilizzare greed tutti i caratteri fino all'ultimo gruppo di cifre.

years1 <- c('2005-', '2003-', '1984-1992, 1996-') 
unlist(str_extract_all(years1, perl('.*\\K\\d{4}'))) 
# [1] "2005" "2003" "1996" 
Problemi correlati