Преобразование года и месяца (формат «гггг-мм») в дату? - PullRequest
79 голосов
/ 05 июня 2011

У меня есть набор данных, который выглядит следующим образом:

Month    count
2009-01  12
2009-02  310
2009-03  2379
2009-04  234
2009-05  14
2009-08  1
2009-09  34
2009-10  2386

Я хочу построить данные (месяцы как значения x и считаются как значения y)Поскольку в данных есть пробелы, я хочу преобразовать информацию за месяц в дату.Я попробовал:

as.Date("2009-03", "%Y-%m")

Но это не сработало.В чем дело?Похоже, что as.Date () требует также день и не может установить стандартное значение для дня?Какая функция решает мою проблему?

Ответы [ 7 ]

66 голосов
/ 05 июня 2011

Поскольку даты соответствуют числовому значению и дате начала, вам действительно нужен день.Если вам действительно нужно, чтобы ваши данные были в формате даты, вы можете просто зафиксировать день на первое число каждого месяца вручную, вставив его в дату:

month <- "2009-03"
as.Date(paste(month,"-01",sep=""))
52 голосов
/ 05 июня 2011

Попробуй это.(Здесь мы используем text=Lines, чтобы сохранить пример самодостаточным, но на самом деле мы бы заменили его именем файла.)

Lines <- "2009-01  12
2009-02  310
2009-03  2379
2009-04  234
2009-05  14
2009-08  1
2009-09  34
2009-10  2386"

library(zoo)
z <- read.zoo(text = Lines, FUN = as.yearmon)
plot(z)

Ось X не так хороша с этими данными, но если у вас есть большев действительности это может быть нормально, или вы можете использовать код для необычной оси X, показанный в разделе примеров ?plot.zoo.

Серия зоопарков, z, созданная выше, имеет "yearmon" указатель времени и выглядит следующим образом:

> z
Jan 2009 Feb 2009 Mar 2009 Apr 2009 May 2009 Aug 2009 Sep 2009 Oct 2009 
      12      310     2379      234       14        1       34     2386 

"yearmon" также может использоваться отдельно:

> as.yearmon("2000-03")
[1] "Mar 2000"

Примечание:

  1. "yearmon" сортировка объектов класса в календарном порядке.

  2. Это будет отображать месячные точки с равными интервалами, что, вероятно, является желаемым;однако, если необходимо построить точки с неравномерно распределенными интервалами, разделенными пропорционально количеству дней в каждом месяце, преобразовайте индекс z в "Date" class: time(z) <- as.Date(time(z)).

23 голосов
/ 07 февраля 2014

Самое краткое решение, если вам нужно, чтобы даты были в формате Дата:

library(zoo)
month <- "2000-03"
as.Date(as.yearmon(month))
[1] "2000-03-01"

as.Date зафиксирует первый день каждого месяца для объекта yearmon для вас.

14 голосов
/ 25 июня 2017

Этого также можно добиться с помощью функций parse_date_time или fast_strptime из пакета lubridate:

> parse_date_time(dates1, "ym")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"

> fast_strptime(dates1, "%Y-%m")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"

Разница между этими двумя заключается в том, что parse_date_time допускает спецификацию формата в стиле lubridate, тогда как fast_strptime требует той же спецификации формата, что и strptime.

Для указания часового пояса вы можете использовать tz -параметр:

> parse_date_time(dates1, "ym", tz = "CET")
[1] "2009-01-01 CET" "2009-02-01 CET" "2009-03-01 CET"

Если в данных даты и времени есть отклонения, вы можете использовать параметр truncated, чтобы указать, сколько отклонений допускается:

> parse_date_time(dates2, "ymdHMS", truncated = 3)
[1] "2012-06-01 12:23:00 UTC" "2012-06-01 12:00:00 UTC" "2012-06-01 00:00:00 UTC"

Использованные данные:

dates1 <- c("2009-01","2009-02","2009-03")
dates2 <- c("2012-06-01 12:23","2012-06-01 12",'2012-06-01")
10 голосов
/ 08 марта 2017

Использование в любое время пакет:

library(anytime)

anydate("2009-01")
# [1] "2009-01-01"
4 голосов
/ 17 декабря 2015

Действительно, как уже упоминалось выше (и в других местах SO), чтобы преобразовать строку в дату, вам нужна конкретная дата месяца.На странице руководства as.Date():

Если в строке даты не указана дата полностью, возвращаемый ответ может зависеть от системы.Наиболее распространенным поведением является предположение, что текущий, отсутствующий год, месяц или день.Если он указывает неверную дату, надежные реализации выдадут ошибку, а дата будет отображена как NA.К сожалению, некоторые распространенные реализации (такие как glibc) ненадежны и предполагают предполагаемое значение.

Простым решением было бы вставить дату "01" к каждой дате и использовать strptime() дляукажите это как первый день этого месяца.


Для тех, кто ищет немного больше информации о датах и ​​времени обработки в R:

В R времена используют классы POSIXct и POSIXlt, а даты используют класс Date.

Даты сохраняются как количество дней с 1 января 1970 года, а время - как число.секунд с 1 января 1970 года.

Так, например:

d <- as.Date("1971-01-01")
unclass(d)  # one year after 1970-01-01
# [1] 365

pct <- Sys.time()  # in POSIXct
unclass(pct)  # number of seconds since 1970-01-01
# [1] 1450276559
plt <- as.POSIXlt(pct)
up <- unclass(plt)  # up is now a list containing the components of time
names(up)
# [1] "sec"    "min"    "hour"   "mday"   "mon"    "year"   "wday"   "yday"   "isdst"  "zone"  
# [11] "gmtoff"
up$hour
# [1] 9

Для выполнения операций с датами и временем:

plt - as.POSIXlt(d)
# Time difference of 16420.61 days

И для обработки дат,Вы можете использовать strptime() (заимствуя эти примеры из страницы руководства):

strptime("20/2/06 11:16:16.683", "%d/%m/%y %H:%M:%OS")
# [1] "2006-02-20 11:16:16 EST"

# And in vectorized form:
dates <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")
strptime(dates, "%d%b%Y")
# [1] "1960-01-01 EST" "1960-01-02 EST" "1960-03-31 EST" "1960-07-30 EDT"
0 голосов
/ 09 ноября 2016

Я думаю, что решение @ ben-rollert - хорошее решение.

Вам просто нужно быть осторожным, если вы хотите использовать это решение в функции внутри нового пакета.

При разработке пакетов рекомендуется использовать синтаксис packagename::function_name() (см. http://kbroman.org/pkg_primer/pages/depends.html).

. В этом случае вы должны использовать версию as.Date(), определяемуюzoo library.

Вот пример:

> devtools::session_info()
Session info ----------------------------------------------------------------------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.3.1 (2016-06-21)
 system   x86_64, linux-gnu           
 ui       RStudio (1.0.35)            
 language (EN)                        
 collate  C                           
 tz       <NA>                        
 date     2016-11-09                  

Packages --------------------------------------------------------------------------------------------------------------------------------------------------------

 package  * version date       source        
 devtools   1.12.0  2016-06-24 CRAN (R 3.3.1)
 digest     0.6.10  2016-08-02 CRAN (R 3.2.3)
 memoise    1.0.0   2016-01-29 CRAN (R 3.2.3)
 withr      1.0.2   2016-06-20 CRAN (R 3.2.3)

> as.Date(zoo::as.yearmon("1989-10", "%Y-%m")) 
Error in as.Date.default(zoo::as.yearmon("1989-10", "%Y-%m")) : 
  do not know how to convert 'zoo::as.yearmon("1989-10", "%Y-%m")' to class “Date”

> zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
[1] "1989-10-01"

Поэтому, если вы разрабатываете пакет, хорошей практикой является использование:

zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
...