2015-08-05 9 views
5

Sto tentando di analizzare una data da una stringa di testo. Sto assumendo che il modo migliore per farlo sia regex, ma non ho ancora trovato una soluzione che funzioni.Data di analisi nel formato Mon, DD, YYYY utilizzando RegEx in R

In primo luogo, ho usato un selettore CSS per prendere una data da un sito web.

date <-html_nodes(x=doc, css=".middleheadline+ .topnewsbar b") %>% html_text() 

Questo produce:

[1] "\r\n  Washington,\r\n  Jan 5, 2011" 

Voglio estrarre dalla data stessa (qui, 5 Gennaio 2011) da questa stringa. NOTA: il mese può essere qualsiasi mese, la data può essere qualsiasi data, e l'anno può essere qualsiasi cosa dal 2011-2015, quindi sto cercando di trovare un'espressione che può generalmente analizzare una data nel Mon D [D], Formato YYYY.

Ecco un tentativo:

date <-str_extract_all(string=date, pattern='[A-Z][a-z]{3,4} ([0-9]{1,2}), [0-9]{4}') 

Questo produce character(0)

E un altro:

grep("[A-Z][a-z]{3,4} ([0-9]{1,2}), [0-9]{4}", date, value=TRUE) 

che produce anche character(0)

Qualche consiglio?

+0

forse 'grep (" \\ w {3,4} \\ d {1,2}, \\ d {4}, data, valore = TRUE) 'Non ho ancora provato questo. \\ tag W' corrisponderà caratteri alfabetici, il '\\ d' tag corrisponde cifre. – Benjamin

+1

è la data sempre alla fine della stringa, o sempre dopo l'ultimo' "\ r \ n" '? –

+0

sono d'accordo con implicazione di Joshua che abbiamo bisogno di maggiori informazioni su come apparirà l'input - non solo su come sarà la data. La conversione in un tipo di data reale è abbastanza facile purché possiamo identificare l'input e se è sempre alla fine del stringa di input quindi che lo rende * veramente * facile – Dason

risposta

2

Si potrebbe provare questo: Link

date <-str_extract_all(string=date, pattern='\\w+\\s\\d+(st)?(nd)?(rd)?(th)?,\\s+\\d+') 

HERE test.

+0

Grazie Richard Scriven, ora dovrebbe funzionare – teoreda

+1

Grazie! Ho dovuto aggiungere doppie barre per farlo funzionare: 'date <-str_extract_all (stringa = Data, pattern = '\\ w + \\ s \\ d + (st) (nd) (rd) (th) ?,??? \\ s + \\ d + ') ' –

+0

Ho modificato il post @RachelB. :) – teoreda

2

una funzione per convertire le date:

make_dates <- function(x, date_format=TRUE, split="\n") { 
    dates <- lapply(strsplit(x, split), function(x) { 
    grep("\\w+ \\d+, \\d+", x, value=T)}) 

    if(date_format) { 
    strptime(gsub("\\s", "", dates), format="%b%d,%Y") 
    } else { gsub(".*?(\\w.*)", "\\1", dates)} 
} 

test <- c("\r\n  Washington,\r\n  Jan 5, 2011", 
     "\r\n  Boston,\r\n  Mar 15, 2015") 

make_dates(test) 
#[1] "2011-01-05 EST" "2015-03-15 EDT" 
make_dates(test, FALSE) 
#[1] "Jan 5, 2011" "Mar 15, 2015" 
5

Si può anche provare strsplit(). A volte lo preferisco a un'espressione regolare che intorpidisce la mente.

test <- c("\r\n  Washington,\r\n  Jan 5, 2011", 
    "\r\n  Boston,\r\n  Mar 15, 2015") 

vapply(strsplit(test, ".*\n\\s+"), "[", "", 2) 
# [1] "Jan 5, 2011" "Mar 15, 2015" 

as.Date(vapply(strsplit(test, ".*\n\\s+"), "[", "", 2), "%b %d, %Y") 
# [1] "2011-01-05" "2015-03-15" 
1

Ecco una regex che restituirà una data in una stringa in una varietà di formati MDY, con una varietà di separatori. Assicurati di impostare l'opzione case insensitve nella tua procedura.

Fa qualche rudimentale verifica degli errori, ma consentirà anni a due cifre; e consentirebbe anche una data come del 31 Feb, 2015

\b((?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*|(?:0?[1-9]|1[0-2]))(?:\s*([- /.])\s*)(?:(0?[1-9]|[12]\d|3[01])(?:st|nd|rd|th)?),?\2((?:19|2\d)?\d{2})\b 
0

penso che questo sarebbe sufficiente:

[A-Z][a-z]{2} \d{1,2}, 201[1-4] 

Demo: https://regex101.com/r/eW3jV6/1

Che mese di abbreviazione è lungo 5 o 4 caratteri? Il tuo regex non funziona perché hai [A-Z][a-z]{3,4} che dice un carattere alfa maiuscolo seguito da tre o quattro caratteri alfanumerici minuscoli. Non ho familiarità con un mese con un'abbreviazione di 5 caratteri.

La stringa Jan è lunga 3 caratteri ma solo 2 di questi caratteri sono in minuscolo.

Demo della vostra regex corrente: https://regex101.com/r/bJ6gT3/1

Se c'è una possibilità di molteplici spazi tra il mese e il giorno e/o l'anno aggiungere in \h+; o se non ci possono essere spazi, rendilo \h*.

+0

Alcune delle date utilizzano l'abbreviazione di 3 caratteri, mentre altre sono nomi di mese completo (tra 4 e 9 caratteri). Sto cercando di trovare qualcosa che si occupi di tutte le permutazioni del nome del mese. –

+0

È possibile utilizzare il raggruppamento di qualcosa come '(Jan (uary)? | Feb (uraria)? | Mar (ch)?)' Ecc. Quindi il controllo giorno e anno. – chris85

Problemi correlati