2016-08-30 1 views
5

Fehle ich etwas? Ich kann nicht herausfinden, wie die folgenden Date s zu konvertieren:Format für Ordinaldaten?

ord_dates <- c("September 1st, 2016", "September 2nd, 2016", 
       "September 3rd, 2016", "September 4th, 2016") 

?strptime keine Abkürzung für die Ordnungs Suffix Liste angezeigt wird, und es wird nicht automatisch behandelt:

as.Date(ord_dates, format = c("%B %d, %Y")) 
#[1] NA NA NA NA 

Gibt es ein Token für die Behandlung von ignorierten Zeichen im format Argument? Ein Token fehlt mir?

Best I mit oben kommen kann ist (es kann eine kürzere regex, aber die gleiche Idee):

as.Date(gsub("([0-9]+)(st|nd|rd|th)", "\\1", ord_dates), format = "%B %d, %Y") 
# [1] "2016-09-01" "2016-09-02" "2016-09-03" "2016-09-04" 

wie diese Art von Daten scheinen sollte relativ häufig sein; Fehle ich etwas? Genießen Sie

+2

Hier ist eine kürzere Regex: 'as.Date (sub (" ([0-9] +). *, "," \\ 1 ", ord_dates), Format = c ("% B% d% Y ")) ' – Frank

+0

@Frank ist' sub' schneller als 'gsub' übrigens? Ich stelle mir das so vor ... – MichaelChirico

+0

Hm, ich bin kein Regex-Experte, aber ich denke, es sollte sein, wenn Strings lang sind und das erste Match früh in der Zeichenfolge ist (so muss es den Rest nicht durchlaufen). – Frank

Antwort

5

die Macht der lubridate:

library(lubridate)  
mdy(ord_dates) 

[1] "2016-09-01" "2016-09-02" "2016-09-03" "2016-09-04" 

Intern lubridate hat keine spezielle Konvertierungsspezifikationen, die dies ermöglichen. Eher verwendet lubridate zuerst (durch intelligentes Raten) das Format "%B %dst, %Y". Dies erhält das erste Element von ord_dates.

Es prüft dann auf NA s und wiederholt sein intelligentes Raten auf den restlichen Elementen und setzt auf "%B %dnd, %Y" fort, um das zweite Element zu erhalten. Es wird auf diese Weise fortgesetzt, bis keine NA übrig sind (was in diesem Fall nach 4 Iterationen der Fall ist), oder bis das intelligente Erraten einen wahrscheinlichen Formatkandidaten nicht hervorbringt.

können Sie sich vorstellen, dies macht lubridate langsamer, und es tut - etwa die Hälfte der Geschwindigkeit von nur die Smart-regex von @alistaire vorgeschlagen unter Verwendung von oben:

set.seed(109123) 
ord_dates <- sample(
    c("September 1st, 2016", "September 2nd, 2016", 
    "September 3rd, 2016", "September 4th, 2016"), 
    1e6, TRUE 
) 

library(microbenchmark) 

microbenchmark(times = 10L, 
       lubridate = mdy(ord_dates), 
       base = as.Date(sub("\\D+,", "", ord_dates), 
           format = "%B %e %Y")) 
# Unit: seconds 
#  expr  min  lq  mean median  uq  max neval cld 
# lubridate 2.167957 2.219463 2.290950 2.252565 2.301725 2.587724 10 b 
#  base 1.183970 1.224824 1.218642 1.227034 1.228324 1.229095 10 a 

Der offensichtliche Vorteil in lubridate ‚Gunst ist seine Prägnanz und Flexibilität.

+1

@MichaelChirico: das ist eine recht großzügige Bearbeitung. –

+1

@JoshuaUlrich ist es sicherlich keine neue Antwort, aber ich dachte, es wäre nützlich, um die Frage hinzuzufügen, um zukünftige Leser meine Bemühungen zu speichern – MichaelChirico

+0

Sehr informativ bearbeiten! – thepule