R: Что такое даты в векторе дат: даты или числовые значения?

Может ли кто-нибудь объяснить, почему в первом цикле каждый элемент моего вектора дат является датой, а во втором каждый элемент моего вектора дат числовой? Спасибо!

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 ответа


Когда вы бежите:

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

Элементы Date , первый цикл правильный.

К сожалению, R не всегда имеет стиль второго цикла. Я полагаю, что проблема заключается в том, что синтаксис for (i in x) обходит методы Date для методов доступа, подобных [ , что он может сделать, потому что классы S3 в R очень тонкие и не мешают вам не использовать их намеченные интерфейсы. Это может сбивать с толку, потому что что-то вроде 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, которые вы также можете увидеть ниже, если вы конвертируете их обратно в Date с этим origin .

 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' , вы увидите, что for(var in seq) определяется только тогда, когда seq имеет значение «Выражение, is.vector(x) в векторе», а is.vector(x) - FALSE . Таким образом, документация говорит (может быть, не так ясно), что поведение здесь не определено, поэтому поведение является неожиданным.

Как упоминает Джоран, as.vector(x) возвращает числовой вектор, такой же, как unclass(x) упомянутый Calum You.


Есть идеи?

10000