Tibbles 拒绝 lubridate 的 duration 和 period 对象
Tibbles reject lubridate's duration and period objects
有效代码:duration
和 period
对象
下面的代码分别成功生成了一个duration
对象和一个period
对象。
> lubridate::as.duration(1)
[1] "1s"
> lubridate::seconds(1)
[1] "1S"
不起作用的代码:tibble
s
中的 duration
和 period
对象
但是,当我尝试使用 duration
或 period
对象创建 tibble
时,我收到了无意义的错误消息。
> 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.
有效的代码:data.frame
s
中的 duration
和 period
个对象
用 base::data.frame
替换 tibble::tibble
有效。
> 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.
可能的解释
Hadley 在这个 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")
的 class 似乎导致 R
试图强制 x
以引发错误的方式。
此外,考虑到 tibble::tibble
也调用了 as_tibble
(尽管不在 data.frame
上),我会冒险猜测我与 tibble::tibble
的问题具有相同的原因。
包版本
- Tibble:1.4.1
- 润滑:1.7.1
- R: 3.4.3
此问题现已从 pillar v.1.2.1 (https://github.com/r-lib/pillar/issues/88) 开始解决。
有效代码:duration
和 period
对象
下面的代码分别成功生成了一个duration
对象和一个period
对象。
> lubridate::as.duration(1)
[1] "1s"
> lubridate::seconds(1)
[1] "1S"
不起作用的代码:tibble
s
duration
和 period
对象
但是,当我尝试使用 duration
或 period
对象创建 tibble
时,我收到了无意义的错误消息。
> 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.
有效的代码:data.frame
s
duration
和 period
个对象
用 base::data.frame
替换 tibble::tibble
有效。
> 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.
可能的解释
Hadley 在这个 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")
的 class 似乎导致 R
试图强制 x
以引发错误的方式。
此外,考虑到 tibble::tibble
也调用了 as_tibble
(尽管不在 data.frame
上),我会冒险猜测我与 tibble::tibble
的问题具有相同的原因。
包版本
- Tibble:1.4.1
- 润滑:1.7.1
- R: 3.4.3
此问题现已从 pillar v.1.2.1 (https://github.com/r-lib/pillar/issues/88) 开始解决。