2013-02-18 4 views
12

У меня есть данные на неделю в форме yyyy-ww где ww - номер недели в две цифры. Диапазон данных 2007-01 - 2010-30. Соглашение о подсчете недель - это ISO 8601, который, как вы можете видеть здесь, on Wikipedia's "Week number" article, иногда достигает 53 недель в году. Например, для этой системы в 2009 году было 53 недели, см. Номера недель в this ISO 8601 calendar. (Другие годы, согласно статье Википедии, 53-й недели довольно редко.)53-я неделя года в R?

В основном я хочу прочитать дату недели в, преобразовать его в Date объект и сохранить это в отдельной колонке в data.frame. В качестве теста я преобразовал объекты Date в формат yyyy-ww по format([Date-object], format = "%Y-%W", и это заставило ошибку на 2009-53. Эта неделя не может быть интерпретирована как дата на R. Это очень странно, так как другие годы, которые не имеют 53-я неделя (в стандарте ISO 8601), преобразуются штрафом, например 2007-53, тогда как другие годы, которые также не имеют 53-й недели (в стандарте ISO 8601), также терпят неудачу , такие как 2008-53

Следующий минимальный пример демонстрирует проблему.

Минимальный пример:

dates <- c("2009-50", "2009-51", "2009-52", "2009-53", "2010-01", "2010-02") 
as.Date(x = paste(dates, 1), format = "%Y-%W %w") 
# [1] "2009-12-14" "2009-12-21" "2009-12-28" NA   "2010-01-04" 
# [6] "2010-01-11" 

other.dates <- c("2007-53", "2008-53", "2009-53", "2010-53") 
as.Date(x = paste(other.dates, 1), format = "%Y-%W %w") 
# [1] "2007-12-31" NA   NA   NA  

Вопрос в том, как я могу получить R принять номер недели в формате ISO 8601?

Примечание: Этот вопрос суммирует проблему, с которой я боролся в течение нескольких часов. Я искал и нашел различные полезные сообщения, такие как this, но никто не решил проблему.

+1

Это могло бы быть более иллюстративными для сравнения 'as.Date (х = "2009-01 01", формат = "% Y-% W% W")' 'с ISOweek2date (" 2009-W01-1 ")', и вы также должны указать запись для '% W' в' help (strptime) '. – Roland

+0

Не уверен, но я помню, что большая часть обработки даты R фактически обрабатывается системными библиотеками, что означает, что такая проблема (а) будет сильно отличаться от ОС к ОС; (б) может быть особенно изворотливым в Windows; (c) было бы трудно исправить в самом R (как видно из нижеприведенного ответа: «ISOweek» реализует свои собственные алгоритмы, поскольку в системных библиотеках Windows отсутствуют вещи) –

+0

@BenBolker Поведение определяется в 'help (strptime)' , – Roland

ответ

10

Пакет ISOweek управляет нумерациями недель в стиле ISO 8601, конвертирует в Date объектов в R. См. ISOweek для получения дополнительной информации. Продолжая приведенные выше примеры, нам сначала нужно немного изменить форматирование. Они должны быть в форме yyyy-Www-w, а не yyyy-ww, то есть 2009-W53-1. Последняя цифра определяет, какой день недели использовать для идентификации недели, в этом случае это понедельник. Номер недели должен быть двухзначным.

library(ISOweek) 

dates <- c("2009-50", "2009-51", "2009-52", "2009-53", "2010-01", "2010-02") 
other.dates <- c("2007-53", "2008-53", "2009-53", "2010-53") 

dates <- sub("(\\d{4}-)(\\d{2})", "\\1W\\2-1", dates) 
other.dates <- sub("(\\d{4}-)(\\d{2})", "\\1W\\2-1", other.dates) 

## Check: 
dates 
# [1] "2009-W50-1" "2009-W51-1" "2009-W52-1" "2009-W53-1" "2010-W01-1" 
# [6] "2010-W02-1" 

(iso.date <- ISOweek2date(dates))    # deal correctly 
# [1] "2009-12-07" "2009-12-14" "2009-12-21" "2009-12-28" "2010-01-04" 
# [6] "2010-01-11" 
(iso.other.date <- ISOweek2date(other.dates)) # also deals with this 
# [1] "2007-12-31" "2008-12-29" "2009-12-28" "2011-01-03" 

## Check that back-conversion works: 
all(date2ISOweek(iso.date) == dates) 
# [1] TRUE 

## This does not work for the others, since the 53rd week of 
## e.g. 2008 is back-converted to the first week of 2009, in 
## line with the ISO 6801 standard. 
date2ISOweek(iso.other.date) == other.dates 
# [1] FALSE FALSE TRUE FALSE