Работающий код: объекты duration
и period
Следующий код успешно создает объект duration
и объект period
соответственно.
> lubridate::as.duration(1)
[1] "1s"
> lubridate::seconds(1)
[1] "1S"
Неработающий код: объекты duration
и period
в tibble
s
Однако, когда я пытаюсь создать tibble
s с помощью объекта duration
или period
, я получаю неинформативные сообщения об ошибках.
> tibble::tibble(y = lubridate::as.duration(1))
Error: Incompatible duration classes (Duration, numeric). Please coerce with `as.duration`.
> tibble::tibble(y = lubridate::seconds(1))
Error in x < 0 : cannot compare Period to Duration:
coerce with 'as.numeric' first.
Работающий код: объекты duration
и period
в data.frame
s
Замена tibble::tibble
на base::data.frame
работает.
> data.frame(y = lubridate::as.duration(1))
y
1 1s
> data.frame(y = lubridate::seconds(1))
y
1 1S
Неработающий код - принуждение этих data.frame
к tibbles
Использование tibble::as_tibble
для приведения этих data.frame
к tibbles
дает ту же ошибку, что и раньше.
> tibble::as_tibble(data.frame(y = lubridate::as.duration(1)))
Error: Incompatible duration classes (Duration, numeric). Please coerce with `as.duration`.
> tibble::as_tibble(data.frame(y = lubridate::seconds(1)))
Error in x < 0 : cannot compare Period to Duration:
coerce with 'as.numeric' first.
Возможное объяснение
Хэдли упоминает кое-что в этом выпуске Github - https://github.com/tidyverse/tibble/issues/326 - о столбцах S4, которые включают as.duration
и as.period
. О несовместимости ничего особо не говорится.
Покопавшись в исходном коде, я обнаружил следующую цепочку зависимостей, которые выдают такое же сообщение об ошибке: as_tibble.data.frame --> list_to_tibble --> new_tibble
В tibble:::list_to_tibble
единственный аргумент, переданный в tibble::new_tibble
, - это x
. Следовательно, subclass
присваивается значение по умолчанию NULL
, а предпоследняя строка tibble::new_tibble
становится
class(x) <- c("tbl_df", "tbl", "data.frame")
У объектов есть структура, но попытка вызвать их напрямую приводит к ошибке.
> x <- data.frame(y = lubridate::as.duration(1))
> class(x) <- c("tbl_df", "tbl", "data.frame")
> str(x)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1 obs. of 1 variable:
$ x:Formal class 'Duration' [package "lubridate"] with 1 slot
.. ..@ .Data: num 1
> x
Error: Incompatible duration classes (Duration, numeric). Please coerce with `as.duration`.
> x <- data.frame(y = lubridate::seconds(1))
> class(x) <- c("tbl_df", "tbl", "data.frame")
> str(x)
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 1 obs. of 1 variable:
$ y:Formal class 'Period' [package "lubridate"] with 6 slots
.. ..@ .Data : num 1
.. ..@ year : num 0
.. ..@ month : num 0
.. ..@ day : num 0
.. ..@ hour : num 0
.. ..@ minute: num 0
> x
Error in x < 0 : cannot compare Period to Duration:
coerce with 'as.numeric' first.
Следовательно, кажется, что присвоение класса data.frame
x
вектору c("tbl_df", "tbl", "data.frame")
заставляет R
попытаться принудить x
таким образом, который вызывает ошибку.
Кроме того, учитывая, что tibble::tibble
также вызывает as_tibble
(хотя и не на data.frame
), я рискну предположить, что мои проблемы с tibble::tibble
имеют ту же причину.
Версии пакета
- Таблица: 1.4.1
- Lubridate: 1.7.1
- R: 3.4.3