如果tibble中包含difftime
变量,并且指定的观察数等于其他变量,则保持变量的类。
tibble::tibble(a = c(1,2), b = as.difftime(c(1,2), units = "hours"))
# A tibble: 2 x 2
a b
<dbl> <time>
1 1 1 hours
2 2 1 hours
但是,如果difftime
变量中指定的观察数量是另一个变量中观察数量的适当因子,那么difftime
变量将被回收,那么变量以静默方式更改为numeric
:
tibble::tibble(a = c(1,2), b = as.difftime(1, units = "hours"))
# A tibble: 2 x 2
a b
<dbl> <dbl>
1 1 1
2 2 1
是否会出现这种行为差异,因为鼓励tidyverse
用户使用period
提供的duration
或lubridate
个对象来指定时间,而不是基于R&#39 ; s difftime
个对象?或者这是一个意想不到的错误?
使用tibble::data_frame
和dplyr::data_frame
时会出现同样的问题,但我相信将来可能会弃用这些问题。
要清楚,以下调用不会以静默方式更改时间类型变量的类:
tibble::tibble(a = c(1,2), b = lubridate::as.period("1H"))
# A tibble: 2 x 2
a b
<dbl> <S4: Period>
1 1 1H 0M 0S
2 2 1H 0M 0S
tibble::tibble(a = c(1,2), b = lubridate::as.duration("1H"))
# A tibble: 2 x 2
a b
<dbl> <S4: Duration>
1 1 3600s (~1 hours)
2 2 3600s (~1 hours)
答案 0 :(得分:2)
您所看到的行为源于数据帧创建过程中矢量回收过程中非常特殊的行为。如您所知,传递给data.frame
函数的对象应具有相同的行数。但是如果需要, 原子矢量 将被重复使用多次。这提出了以下问题:以下不起作用:
dff <- data.frame(a=c(1,2), b=as.difftime(1, units="hours"))
上面的代码引发了以下错误:
data.frame出错(a = c(1,2),b = as.difftime(1,units =“hours”)) :参数意味着行数不同:2,1
事实证明,这不起作用的原因是因为difftime
个对象的向量不被识别为原子向量。您可以查看以下内容:
is.vector(as.difftime(1, units="hours"))
返回:
[1] FALSE
结果,当data.frame
函数尝试回收列b
时,它首先检查该列是否实际上是一个向量(带is.vector
)。由于返回FALSE
,回收不会继续;因此返回了错误。
因此,随后的问题是: 为什么不将{b}列转换为as.vector
?
这实际上是一个好主意,期望as.vector
删除结果向量的所有属性 ,包括名称。你可以看到以下内容:
as.vector(as.difftime(1, units="hours"))
返回:
[1] 1
强制过程中difftime
对象的所有属性都丢失了。这使我认为tibble::data_frame
函数在生成as.vector
的过程中实际使用data_frame
。因此,我们看到以下行为:
data_frame(a=c(1,2), b=as.difftime(1, units="hours"))
返回
# A tibble: 2 x 2
a b
<dbl> <dbl>
1 1 1
2 2 1
我猜结论与@agstudy达到的结论相同:要维护difftime
对象,您可能必须使用list
列b
,如下所示:
tibble::tibble(a = c(1,2), b = list(as.difftime(1, units = "hours")))
我希望这在某种程度上证明是有用的。
答案 1 :(得分:0)
我不认为tibble
鼓励使用lubridate
(即使我鼓励你使用它)做类似日期的处理,但它更像是矢量如何的问题在回收时在内部创建。事实上,当您使用c
和list
时,您可以重现相同的回收行为。例如,使用c
您将失去输入:
c(as.difftime(c(1), units = "hours"),1)
### Time differences in hours
### [1] 1 1
但使用list
会保留时差类型:
list(as.difftime(c(1), units = "hours"),2)
# [[1]]
# Time difference of 1 hours
#
# [[2]]
# [1] 2
将list
应用于tibble,您可以“保存”类类型:
tibble::tibble(a = c(1,2),
b = list(as.difftime(c(1), units = "hours")))
# A tibble: 2 x 2
# a b
# <dbl> <list>
# 1 1 <time [1]>
# 2 2 <time [1]>
但这很难在以后操纵。在这种情况下最好使用lubridate
。