2015-05-20 14 views
7

Sto usando il pacchetto lubridate per analizzare un vettore di date eterogeneo-formattati e convertirli in stringa, in questo modo:Perché il pacchetto R lubridate non è in grado di analizzare il vettore con più formati?

parse_date_time(c('12/17/1996 04:00:00 PM','4/18/1950 0130'), c('%m/%d/%Y %I:%M:%S %p','%m/%d/%Y %H%M')) 

questo è il risultato:

[1] NA NA 
Warning message: 
All formats failed to parse. No formats found. 

Se rimuovo il %p nella prima stringa di formato, analizza erroneamente la prima stringa di data e non analizza ancora la seconda, in questo modo:

[1] "1996-12-17 04:00:00 UTC" NA      
Warning message: 
1 failed to parse. 

Il tempo 4PM nella stringa viene analizzato a 4AM nel risultato.

Qualcuno ha sperimentato questo strano comportamento?

+0

Sono in grado di replicare l'errore. 'parse_date_time (x = mydates, orders = c ('m/d/YI: M: S p', 'm/g/Y HM'), locale =" eng ")' indica il valore corretto per il primo ma non la seconda data/ora. 'parse_date_time (mydates1, ordini = c ('% m /% d /% Y% H% M'))' non funziona ma .... 'strptime (mydates1, format ="% m /% d /% Y% H% M ")' funziona comunque ... quando 'mydates1' è solo la seconda data' 4/18/1950 0130' – jalapic

+0

Credo che il problema sia con il '0130' del secondo stringa. Se lo cambi in '4/18/1950 01: 30', credo che le cose funzioneranno come previsto. – JasonAizkalns

+0

@JasonAizkalns '0130' può essere analizzato da solo: 'parse_date_time ('0130', '% H% M')' dà '" 0-01-01 01:30:00 UTC "'. –

risposta

1

Questo probabilmente si riferisce alle impostazioni locali del sistema .

  • parse_date_time {lubridate}

    p: AM Indicatore/PM nel locale. Utilizzato in combinazione con I e non con H. Una stringa vuota in alcune impostazioni locali.

Poiché le diverse lingue hanno stringa diversa per AM/PM, se le impostazioni internazionali non è l'inglese, lubridate non preleverà l'indicatore AM/PM, anche se si specifica di esso.

Le impostazioni locali nel sistema operativo possono includere lingua di visualizzazione, formato dell'ora, fusi orari. Sto usando finestre inglesi con fuso orario degli Stati Uniti e impostazioni locali cinesi, quindi ho combattuto anche con AM/PM in fase di analisi del tempo.

Sys.getlocale("LC_TIME") 
[1] "Chinese (Simplified)_China.936" 

È possibile specificare impostazioni locali in parse_date_time {lubridate}, ma non ha funzionato per me in un primo momento:

Sys.setlocale("LC_TIME", "en_US") 
[1] "" 
Warning message: 
In Sys.setlocale("LC_TIME", "en_US") : 
    OS reports request to set locale to "en_US" cannot be honored 
  • locales {base}

    Il locale descrive gli aspetti dell'internazionalizzazione di un programma . Inizialmente molti aspetti delle impostazioni locali di R sono impostati su "C" (che è l'impostazione predefinita per il linguaggio C e riflette l'utilizzo del Nord America). strptime per gli usi di category = "LC_TIME".

poi ho trovato this e usato questo per il successo:

Sys.setlocale("LC_TIME", "C") 
[1] "C" 

Dopo questo il parsing funziona:

parse_date_time('12/17/1996 04:00:00 PM', '%m/%d/%Y %I:%M:%S %p') 
[1] "1996-12-17 16:00:00 UTC" 

È anche possibile specificare il fuso orario e impostazioni locali

parse_date_time('12/17/1996 04:00:00 PM', '%m/%d/%Y %I:%M:%S %p', tz = "America/New_York", locale = "C") 
[1] "1996-12-17 16:00:00 EST" 
+0

Hai ragione che le versioni locali sono il problema con AM/PM. C'è un [numero] dedicato (https://github.com/hadley/lubridate/issues/327) aperto per questo. Nota che il problema dell'OP non riguarda solo PM/AM. – VitoshKa

0

Il problema con la parte %p è locale. Vedi questo issue.

L'incapacità di analizzare ha a che fare con il modo in cui l'indovino lubridato funziona.

Ci sono due modi per la lubrificazione dei formati, flessibile ed esatto. Con il flex matching tutti gli elementi numerici possono avere una lunghezza flessibile (ad esempio, sia 4 che 04 per giorno lavoreranno), ma poi, ci devono essere separatori non numerici tra gli elementi. Per il matcher esatto non sono necessari separatori non numerici, ma gli elementi devono avere il numero esatto di cifre (come 04).

Sfortunatamente non è possibile combinare entrambi i matcher in un'unica espressione. Sarebbe estremamente difficile risolvere questo problema e preservare l'attuale flessibilità del parser lubridato.

Nel tuo esempio

> parse_date_time('4/18/1950 0130', 'mdY HM') 
[1] NA 
Warning message: 
All formats failed to parse. No formats found. 

si desidera eseguire corrispondenza flex da parte della data 4/18/1950 e la corrispondenza esatta su part-time 0130.

Si prega di notare che se il vostro data-ora è completamente flex, o completamente formato exact l'analisi funzionerà come previsto:

> parse_date_time('04/18/1950 0130', 'mdY HM') 
[1] "1950-04-18 01:30:00 UTC" 
> parse_date_time('4/18/1950 1:30', 'mdY HM') 
[1] "1950-04-18 01:30:00 UTC" 

I lubridate 1.4.1 "fissa" questo con l'aggiunta di un nuovo argomento di parse_date_time, exact=FALSE . Se impostato su TRUE, l'argomento orders viene interpretato come contenente i formati esatti strptime e non viene eseguita alcuna ipotesi o addestramento. In questo modo è possibile aggiungere tutti i formati esatti che si desidera e si otterrà anche in velocità perché non viene eseguita alcuna ipotesi.

> parse_date_time(c('12/17/1996 04:00:00','4/18/1950 0130'), 
+     c('%m/%d/%Y %I:%M:%S','%m/%d/%Y %H%M'), 
+     exact = T) 
[1] "1996-12-17 04:00:00 UTC" "1950-04-18 01:30:00 UTC" 

relazione a ciò, v'è stato un esplicito requested chiedere una tale opzione.

Problemi correlati