2015-11-12 2 views
7

У меня есть кадр данных, где дата хранится как double например, 1993.09 1993.10 1993.11 1993.12as.Date из формата «YYYY.mm»

Я хочу, чтобы преобразовать его в формат даты (с дней всегда 1).

Насколько я понимаю, as.Date() хочет ввести строку. Однако по какой-то причине, когда я конвертирую свои даты в строку sapply(dates, as.character), нули после исчезновения, эффективно конвертируя октябрь в январь, приводя к двум годам в год.

dates 
1993.07 1993.08 1993.09 1993.10 1993.11 1993.12 
sapply(dates, as.character) 
sub("[.]", " ", dates) 
"1993 07" "1993 08" "1993 09" "1993 1" "1993 11" "1993 12" 

Есть ли более простой способ преобразования дат? Или где я испортил?

dput:

c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.1, 1993.11, 1993.12) 

ответ

9

Ваша проблема заключается в том, что у вас есть то, что является строка символов, но выглядит как цифровой и вы не позаботились об этом во время импорта. R не различает 1993.1 и 1993.10. Оба имеют одинаковое число. Таким образом, as.character(1993.10) возвращает "1993.1". Вам нужно использовать функцию форматирования, чтобы убедиться, что вы получаете две цифры после периода, потому что as.Date"1993.1" и "1993.01" - это тот же месяц.

x <- c(1993.09, 1993.10, 1993.11, 1993.12) 
as.Date(sprintf("%.2f.01", x), format = "%Y.%m.%d") 
#[1] "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 

Конечно, x должны быть импортированы в качестве персонажа, чтобы начать с.

+0

Параметр 'dput' является' х <- с (1993,09, 1993,1, 1993,11, 1993,12) ', но ваши решения до сих пор работает. –

+0

@DavidArenburg R не заботится, если вы дадите ему '1993.1' или' 1993.10'. Это идентичный двойной. – Roland

2

Использование paste0 добавить день в и поиска значения для форматирования даты из ?strptime. Если у вас возникли проблемы с двойной строкой форматирования, можно использовать formatC:

txtfield <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
    1993.08, 1993.09, 1993.1, 1993.11, 1993.12) 

as.Date(paste0(formatC(txtfield, digits=2, format="f"),".01"), "%Y.%m.%d") 

Объяснение:

paste0 является сокращенной версией paste что не вставляют пробела между приклеенными элементами.
в formatC, digits указывает количество цифр, которое вы хотите после десятичной метки (в нашем случае мы хотим 2. формат сообщает R, которое используется для форматирования чисел, в нашем случае «f» дает номера чисел в желаемом xxx.xxx Формат:
as.Date конвертирует в формат даты в формате R с «% Y.% m.% d», определяющим полный год (4 цифры), за которым следует точка, а затем числовой месяц (2 цифры), а затем точка, . с последующим численным день

результаты:

[1] "1993-01-01" "1993-02-01" "1993-03-01" "1993-04-01" "1993-05-01" "1993-06-01" 
[7] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 
0

Вам нужно сделать некоторые возился с ул ь. Самым очевидным способом (для меня *) было бы «набить» правую часть значений нулями.

* это довольно большой нюанс

dates <- c(1993.01, 1993.02, 1993.03, 1993.04, 1993.05, 1993.06, 1993.07, 
1993.08, 1993.09, 1993.10, 1993.11, 1993.12) 

library(magrittr) 
library(stringr) 
dates %<>% 
    str_pad(width = 7, side = "right", pad = "0") %>% 
    paste0(".01") %>% 
    as.Date(format = "%Y.%m.%d") 

dates 
6

Если вы действительно хотите конвертировать его в класс "Date", используя первое из месяца, то решение Roland кажется самым прямым, но есть и другие соображения, например, можно ли использовать конец месяца или действительно ли вы хотите представить год-месяцы, используя даты в первую очередь.

пакет зоопарк имеет "yearmon" класс, который может представлять год-месяцев непосредственно без их преобразования даты, а также имеет as.Date.yearmon метод, который имеет frac= аргумент может быть использован для определения доли пути через месяц, чтобы преобразовать если вы хотите "Date" класс.

Во-первых, убедитесь, что даты являются символьными строками. Ввод в вопросе показывает 1993.10 как один из входных данных, поэтому мы должны убедиться, что существует конечный ноль. (Если входы уже являются символами с конечным нолем, то это не проблема. Мы предположили, что худший случай здесь предполагает числовое значение, так что нам нужно явно преобразовать их в характерные укусы с конечным 0, если это необходимо.) Теперь используйте as.yearmon с форматом "%Y.%m". Наконец, используйте as.Date.yearmon для преобразования в класс "Date".

Пожалуй, самое большое преимущество этого подхода заключается в том, что мы могли бы просто оставить результат в "yearmon" класса (т.е. опустить "as.Date" часть, например, as.yearmon(sprintf("%.2f", dates)) или если даты уже были символьные строки, dates.ch, с завершающего 0 в случае "1993.10" то просто as.yearmon(dates.ch, "%Y.%m"), которые на самом деле представляют собой то, что у вас есть лучше, так как на следующий день на самом деле не имеет смысла, учитывая, что его там не было в самом начале. "yearmon" объекты могут быть построены и сортируются в ожидаемом порядке.

Вот преобразование в "Date" класс с использованием "yearmon":

library(zoo) 

dates <- c(1993.07, 1993.08, 1993.09, 1993.1, 1993.11, 1993.12) # test input 


as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m")) # 1st of month 
## [1] "1993-07-01" "1993-08-01" "1993-09-01" "1993-10-01" "1993-11-01" "1993-12-01" 

as.Date(as.yearmon(sprintf("%.2f", dates), "%Y.%m"), frac = 1) # last of month 
## [1] "1993-07-31" "1993-08-31" "1993-09-30" "1993-10-31" "1993-11-30" "1993-12-31" 

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

dates.ch <- c("1993.07", "1993.08", "1993.09", "1993.10", "1993.11", "1993.12") # input 

as.Date(as.yearmon(dates.ch, "%Y.%m")) 

as.Date(as.yearmon(dates.ch, "%Y.%m"), frac = 1) 
+2

ОК. Исправлены. –

+0

Имейте upvote для решения последнего дня месяца. – Roland

+0

Имейте передо мной от меня за воспоминание о пакете зоопарка, забыл об этом! –