2015-05-20 1 views
7

Я использую пакет lubridate разобрать вектор гетерогенно-отформатированных даты и преобразовать их в строку, как это:Почему R пакет lubridate не может анализировать вектор с несколькими форматами?

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')) 

Это результат:

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

Если удалить %p в строке 1-го формата он неправильно разбирает строку 1-го дня и все еще не анализирует вторую, например:

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

Время 4PM в строке обрабатывается в результате 4AM.

Неужели кто-нибудь испытал это странное поведение?

+0

Я могу воспроизвести ошибку. 'parse_date_time (x = mydates, orders = c ('m/d/YI: M: S p', 'm/d/Y HM'), locale =" eng ")' дает правильное значение для первого но не вторая дата/время. 'parse_date_time (mydates1, приказы = с ('% м /% г /% Y% H% M'))' не работает, но .... 'strptime (mydates1, формат ="% м /% d /% Y% H% M ")' работает, хотя ... когда 'mydates1' является только второй датой' 4/18/1950 0130' – jalapic

+0

Я считаю, что проблема связана с '0130' второго строка. Если вы измените его на '4/18/1950 01: 30', я считаю, что все будет работать так, как ожидалось. – JasonAizkalns

+0

@JasonAizkalns '0130' может анализироваться отдельно: 'parse_date_time ('0130', '% H% M')' дает '" 0-01-01 01:30:00 UTC ". –

ответ

1

Это, вероятно, относится к вашей локальной системе .

  • parse_date_time {lubridate}

    р: AM/индикатор PM в локали. Используется в сочетании с I, а не с H. Пустая строка в некоторых локалях.

Поскольку различные языки имеют разные строки для AM/PM, если ваш язык не английский, lubridate не подберут индикатор AM/PM, даже если вы укажете его.

Языковой стандарт в ОС может включать в себя язык отображения, формат времени, часовые пояса. Я использую английские окна с часовым поясом США и китайским языком, поэтому я тоже воевал с AM/PM во время разбора.

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

Вы можете указать локаль в parse_date_time {lubridate}, но он не работает для меня на первом:

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}

    Языковой описывает аспекты интернационализации программы , Первоначально большинство аспектов языка R устанавливаются в «C» (который является значением по умолчанию для языка C и отражает использование в Северной Америке). strptime для использования категории = "LC_TIME".

Тогда я нашел this и использовал для успеха:

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

После этого синтаксический работы:

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" 

Вы также можете указать часовой пояс и регион

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

Вы правы, что локали - проблема с AM/PM. Для этого есть выделенный [выпуск] (https://github.com/hadley/lubridate/issues/327). Обратите внимание, что проблема OP связана не только с PM/AM. – VitoshKa

0

Проблема с %p Часть связана с местностью. См. Это issue.

Неспособность к разборке связана с тем, как работает угадайщик lubridate.

Существует два способа получения lubridate форматов, гибкость и точность. При гибком сопоставлении все числовые элементы могут иметь гибкую длину (например, как 4, так и 04 за день будут работать), но тогда между элементами должны быть нечисловые разделители. Для точного совпадения не обязательно должны быть нечисловые разделители, но элементы должны иметь точное количество цифр (например, 04).

К сожалению, вы не можете комбинировать оба набора в одном выражении. Было бы очень сложно исправить это и сохранить текущую гибкость анализатора lubridate.

В вашем примере

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

вы хотите выполнить гибкое согласование на части даты 4/18/1950 и точное соответствие по времени части 0130.

Пожалуйста, обратите внимание, что если ваша дата-время находится в полностью flex или полностью формат exact синтаксический будет работать, как ожидалось:

> 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" 

The lubridate 1.4.1 «исправления», добавив новый аргумент parse_date_time, exact=FALSE , Когда установлено значение TRUE, аргумент orders интерпретируется как содержащий точные форматы strptime, и никаких угадок или обучения не выполняется. Таким образом, вы можете добавить столько точных форматов, сколько хотите, и вы также получите скорость, потому что никаких угадок вообще не выполняется.

> 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" 

Relatedly, был явный requested просить такой вариант.

Смежные вопросы