Перетворення року та місяця (формат рррр-мм) у дату?


91

У мене є набір даних, який виглядає так:

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 () вимагає також дня і не може встановити стандартне значення для дня? Яка функція вирішує мою проблему?

Відповіді:


57

Спробуйте це. (Тут ми використовуємо, 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"клас: time(z) <- as.Date(time(z)).


76

Оскільки дати відповідають числовому значенню та даті початку, вам справді потрібен день. Якщо вам дійсно потрібні ваші дані у форматі Date, ви можете просто зафіксувати день до першого числа кожного місяця вручну, вставивши його до дати:

month <- "2009-03"
as.Date(paste(month,"-01",sep=""))

Які ще існують формати дат? Я бачив щось із POSIX та щось із ISO, але я не впевнений, що це різні формати. Я думав, що це просто функції, ...
R_User

19
Варто зазначити, що ви можете вказати день таким самим у форматері, щоб ви могли робити as.Date(month, format='%Y-%m-01')і досягати однакових результатів. Мені це "здається" кращим, оскільки вказувати ту саму дату в кожному місяці більше стосується формату дати, а не маніпуляції рядками, але, можливо, це дурниця.
JBecker

21
@JBecker, твоя пропозиція для мене не працює. > as.Date("2016-01", format="%Y-%m-01") # [1] NA. Я використовую R 3.3.1
n8sty

26

Найкоротше рішення, якщо вам потрібні дати у форматі Date:

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

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


23

Ви також можете досягти цього за допомогою функцій parse_date_timeабо fast_strptimeз lubridate-package:

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

перетворивши змінну символу у форматування dateза допомогою parse_date_time, чи є спосіб переглянути її в іншому порядку, ніж "2009-01-01 UTC"використання lubridateпакета? Я хотів би побачити перший день у своєму наборі даних, наприклад 01-01-2009.
user63230

1
@ user63230 Див . ?format; наприклад: format(your_date, "%d-%m-%Y"). У цьому є недолік: ви отримаєте значення символу назад, а не дату.
Яап,

Дякую, але я намагався уникнути formatз тієї причини, яку ви згадали, я думав, що може бути спосіб включити це в lubridateпакет, але, здається, немає.
user63230

12

Використовуючи будь-який пакет:

library(anytime)

anydate("2009-01")
# [1] "2009-01-01"

Це трохи дивно, що він вибирає "01-01", чи є щось у документації щодо вибору? Можливо, ще наочніше, щоб також показати, anydate("2009-03")якщо він завжди обирає перший день місяця.
lmo

@lmo не перевіряв документи, я б сказав, що це "звичайна" практика, коли dd відсутній для вибору 1-го дня.
zx8754

2
Що має сенс. Мене туманно запам’ятали, а потім знайшли, що викликало коментар. З розділу Примітка ?strptime: вхідний рядок не повинен повністю вказувати дату: передбачається, що невизначені секунди, хвилини або години дорівнюють нулю, а неуточнений рік, місяць або день є поточним. (Однак, якщо вказано місяць, день цього місяця повинен бути вказаний% d або% e, оскільки поточний день місяця не повинен бути дійсним для зазначеного місяця.) Схоже, відповідь мегатрона містить подібний фрагмент документації від as.Date.
lmo

роками до 1900 року це не працює. Наприклад, я спробував цеanytime('1870-01')
msh855

5

Дійсно, як було згадано вище (та в інших місцях на 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"

1

Я думаю, що рішення @ ben-rollert є хорошим рішенням.

Ви просто повинні бути обережними, якщо хочете використовувати це рішення у функції всередині нового пакета.

Коли developping пакетів, рекомендується використовувати syntaxe packagename::function_name()(див http://kbroman.org/pkg_primer/pages/depends.html ).

У цьому випадку вам доведеться використовувати версію, as.Date()визначену zooбібліотекою.

Ось приклад:

> 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"))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.