谁能解释一下为什么在第一个循环中我的日期向量的每个元素都是一个日期,而在第二个循环中,我的日期向量的每个元素都是数字? 谢谢!
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))
元素Date
,第一个循环是正确的。
不幸的是,R 并不总是具有第二个循环的风格。我相信问题是for (i in x)
语法绕过了[
等访问器的Date
方法,它可以这样做,因为 R 中的 S3 类非常薄,不会阻止您不使用其预期的接口。这可能会令人困惑,因为像for (i in 1:4) print(i)
这样的东西直接起作用,因为数字是基本向量类型。Date
是 S3,因此强制使用数字。若要查看在第二个循环中打印的数字对象,可以运行以下命令:
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 矢量类型使用正确的访问器,就像您在第一个循环中所做的那样。
当您运行时:
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
如果你看一下?'for'
,你会发现for(var in seq)
只有在seq
是"向量求值的表达式"时才定义,并且is.vector(x)
是FALSE
。因此,文档说(可能不是那么清楚)此处的行为是未定义的,这就是行为出乎意料的原因。
正如 joran 提到的,as.vector(x)
返回一个数字向量,与 Calum You 提到的unclass(x)
相同。