Как я могу преобразовать этот формат даты в формат, принятый lubridate? - PullRequest
0 голосов
/ 16 апреля 2020

Я импортировал данные в R из листа Excel с пакетом readxl.

Лист содержит столбец с датами. Эти даты ведут себя как даты в Excel (я могу изменить форматирование даты в Excel).

Непосредственно после импорта в R с readxl формат выглядит следующим образом:

# A tibble: 1 x 1
  `datum`         
  <dttm>             
1 2010-01-20 21:00:00

Моя цель - использовать функцию lubridate days_in_month для импортируемых дат.

lubridate::days_in_month(df[2,1])

Хотя использование этой функции выдает эту ошибку:

Error in as.POSIXlt.default(x, tz = tz(x)) : 
  do not know how to convert 'x' to class “POSIXlt”

Я сделал несколько тестов для определения формата:

is.Date(df[2,1])
is.POSIXt(df[2,1])
is.instant(df[2,1])

Все дают результат FALSE.

Если я распечатываю один дата получения этого результата:

# A tibble: 1 x 1
  `datum`         
  <dttm>             
1 2010-01-20 21:00:00

Я пробовал несколько преобразований:

df$datum <- as.Date(df$datum, origin = "1899-12-30")
df$datum <- as.Date(as.POSIXct(df$datum, 'GMT'))
df$datum <- as.Date(df$datum, format='%Y-%m-%d')

Хотя результаты тестов, приведенных выше после преобразования, являются ЛОЖНЫМИ.

Если Я делаю первое преобразование как. Дата (df $ datum, origin = "1899-12-30"). После этого результат печати:

# A tibble: 1 x 1
  `datum`
  <date>    
1 2010-01-20


df$datum + 60 gives:
1 2010-03-21

Так что кажется, что он ведет себя как дата, так как я могу добавить 60.

Хотя все тесты дают FALSE и days_in_month от lubridate все еще дает ошибка выше.

Как я могу преобразовать дату в правильный формат, который может обработать lubridate?

Большое спасибо!

1 Ответ

0 голосов
/ 16 апреля 2020

Вас укусили различия в [ между data.frame и tbl_df. Читая ваш файл (присутствующий в комментариях), я в конечном итоге вижу:

df <- readxl::read_excel("example dates.xlsx")
df
# # A tibble: 3 x 2
#   datum               datum2             
#   <dttm>              <dttm>             
# 1 2010-01-01 13:25:00 2010-12-22 23:53:40
# 2 2010-01-23 13:30:00 2011-01-07 23:09:10
# 3 2010-02-16 21:45:00 2011-03-19 01:00:52

# for everybody else
df <- structure(list(datum = structure(c(1262352300, 1264253400, 1266356700), class = c("POSIXct", "POSIXt"), tzone = "UTC"), datum2 = structure(c(1293062020.704, 1294441750.08, 1300496452.128), class = c("POSIXct", "POSIXt"), tzone = "UTC")), row.names = c(NA, -3L), class = c("tbl_df", "tbl", "data.frame"))

Можем ли мы согласиться с тем, что не имеет смысла пытаться конвертировать целый кадр сразу?

as.Date(df)
# Error in as.Date.default(df) : 
#   do not know how to convert 'df' to class "Date"

Тупой вопрос. Хорошо, давайте посмотрим, что происходит с другими вариантами.

df$datum
# [1] "2010-01-01 13:25:00 UTC" "2010-01-23 13:30:00 UTC" "2010-02-16 21:45:00 UTC"
as.Date(df$datum)
# [1] "2010-01-01" "2010-01-23" "2010-02-16"
df[2,1]
# # A tibble: 1 x 1
#   datum              
#   <dttm>             
# 1 2010-01-23 13:30:00
as.Date(df[2,1])
# Error in as.Date.default(df[2, 1]) : 
#   do not know how to convert 'df[2, 1]' to class "Date"

При простом data.frame, [2,1] вернет скаляр, а не фрейм, так что это имеет смысл в базе R:

as.data.frame(df)[2,1]
# [1] "2010-01-23 13:30:00 UTC"
as.Date(as.data.frame(df)[2,1])
# [1] "2010-01-23"

Итак, проблема в том, что tibble заставляет вас быть явным в том, что вы хотите перейти от фрейма к скаляру / вектору.

Обычно это хорошая вещь, Откровенно. Когда вы имеете дело с «нормальным» (не tibble) фреймом и хотите посмотреть группу столбцов, as.data.frame(df[,1:2]), R всегда возвращает data.frame. К сожалению, если вы определяете столбцы программно и он возвращает один столбец, то [ по умолчанию уменьшает его с кадра на вектор: as.data.frame(df)[,1]. Вы можете предотвратить это автоматическое принуждение с помощью drop=, ala as.data.frame(df[,1,drop=FALSE]). Многие (в том числе и я) считают это ошибкой: следует полагаться на df[,cols], чтобы всегда возвращать один и тот же тип объекта, независимо от того, является ли он 20 столбцами или только 1 столбцом. (Я признаю, что есть причины, по которым это происходит, и я не ругаю оригинальных разработчиков R).

Итак, проблема , вызывающая вашу ошибку, заключается в том, что tibble требует от вас быть явным при размещении вашего tbl_df в одной ячейке. Если вы хотите работать с одной ячейкой, используйте df$datum[2] или df[2,1][[1]], чтобы форсировать ее. Если вы хотите работать над целым столбцом, тогда df$datum. И все они работают непосредственно с as.Date, поскольку он знает, как работать с векторами POSIXt (изначально) и numeric / integer (вместе с origin=). К сожалению, df[,1] тиббла не вернет вектор, поэтому as.Date не знает, что с ним делать.

Итог:

as.Date(df$datum[2])
# [1] "2010-01-23"
as.Date(df[2,1][[1]])
# [1] "2010-01-23"
as.Date(df$datum)
# [1] "2010-01-01" "2010-01-23" "2010-02-16"
...