R:在日期向量中,日期是以日期格式还是数值格式表示的?(x[i]和i之间的区别)

6

请问为什么在第一个循环中,我的日期向量的每个元素都是日期,而在第二个循环中,我的日期向量的每个元素都是数字?谢谢!

x <- as.Date(c("2018-01-01", "2018-01-02", "2018-01-02", "2018-05-06"))
class(x)
# Loop 1 - each element is a Date:
for (i in seq_along(x)) print(class(x[i]))
# Loop 2 - each element is numeric:
for (i in x) print(class(i))             
3个回答

8

这些元素是 Date,第一个循环是正确的。

不幸的是,R并不一致地具有第二个循环的样式。我认为问题在于 for (i in x) 语法绕过了 Date 的访问器([)等方法,它可以这样做是因为R中的S3类非常简单,并且不阻止您不使用其预期接口。这可能会令人困惑,因为像 for (i in 1:4) print(i) 这样的代码是直接可行的,因为numeric是基本向量类型。Date 是S3类型,因此被强制转换为numeric。要查看在第二个循环中打印出的numeric对象,可以运行以下内容:

x <- as.Date(c("2018-01-01", "2018-01-02", "2018-01-02", "2018-05-06"))
for (i in x) print(i)
#> [1] 17532
#> [1] 17533
#> [1] 17533
#> [1] 17657

这会给你一个与未分类版本的Date向量相同的东西。这些数字是自Unix时间开始以来的天数,如果您使用该origin将它们转换回Date,也可以在下面看到。
unclass(x)
#> [1] 17532 17533 17533 17657
as.Date(unclass(x), "1970-01-01")
#> [1] "2018-01-01" "2018-01-02" "2018-01-02" "2018-05-06"

因此,我建议您继续使用适当的访问器来处理任何S3向量类型,就像您在第一个循环中所做的那样。


1
@IceCreamToucan 更直接的是,as.vector(x) 返回底层整数。我认为文档在这个问题上过于神秘了。 - joran

3
如果您查看'for',您会发现只有在seq是“评估为向量的表达式”且is.vector(x)FALSE时,for(var in seq)才被定义。因此,文档(可能不太清楚)说明这里的行为是未定义的,这就是为什么行为出乎意料的原因。
正如joran所提到的,as.vector(x)返回数字向量,与Calum You提到的unclass(x)相同。

3
当你运行以下命令时:
for (i in seq_along(x)) print(class(x[i]))

你正在使用一个迭代器i遍历x中的每个元素。这意味着每次你都会得到x中迭代成员的类。
但是,当你运行以下代码时:
for (i in x) print(class(i))

您正在寻找每个成员的类。使用?Date:

日期表示为自1970-01-01以来的天数

这就是为什么您得到数字作为类别的原因。

此外,如果您对每个循环使用print(),您将获得日期和数字:

for (i in seq_along(x)) print(x[i])

[1] "2018-01-01"
[1] "2018-01-02"
[1] "2018-01-02"
[1] "2018-05-06"

并且
for (i in x) print(i)

[1] 17532
[1] 17533
[1] 17533
[1] 17657

最后,如果您想测试R的逻辑,我们可以做类似这样的事情:

x[1] - as.Date("1970-01-01")

从 x 中取第一个元素(“2018-01-01”),并减去“1970-01-01”,也就是第一个日期。我们的输出将是:
Time difference of 17532 days

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接