drop_na () не может работать с объектом POSIX-lt - PullRequest
0 голосов
/ 06 октября 2018

В соответствии с заголовком я делаю простой пример для проверки drop_na {tidyr}:

library(tidyr)
library(dplyr)

# (1.) produce a dataset with two POSIX type "ct" and "lt"

data <- data.frame(n = 1:5)
data$ct <- as.POSIXct(Sys.time() + rnorm(5) * 1000)
data$lt <- as.POSIXlt(Sys.time() + rnorm(5) * 1000)
str(data)

# $ n : int  1 2 3 4 5
# $ ct: POSIXct, format: "2018-10-07 03:02:28" ...
# $ lt: POSIXlt, format: "2018-10-07 02:37:26" ...


# (2.) assign the third values of "ct" and "lt" to NA

data[3, c("ct", "lt")] <- NA


# (3.) use different function to remove rows with NA

data %>% is.na()               # identify NAs in both "ct" and "lt"
data %>% drop_na('ct')         # drop NA from "ct"
data %>% drop_na('lt')         # NOT drop NA from "lt"
data[c(1, 2)] %>% na.omit()    # drop NA from "ct"
data[c(1, 3)] %>% na.omit()    # NOT drop NA from "lt"

Из приведенного выше вывода, если в переменных POSIX-lt есть NA, может быть только is.na()используется для удаления строк с NA.

Я приблизительно знаю разницу между POSIX "ct" и "lt".

  • POSIXct представляет количество секунд с начала 1970 годакак числовой вектор.
  • POSIXlt - именованный список векторов, представляющих.

Таким образом, кто-то может объяснить, почему пропущенные значения POSIXlt не могут быть идентифицированы с помощью drop_na()и na.omit()?

1 Ответ

0 голосов
/ 07 октября 2018

Краткий ответ: используйте POSIXct, если вам действительно не нужен POSIXlt

Более длинный ответ:

POSIXlt - сложная и капризная структура данных.См .:

> str(c(as.POSIXlt(Sys.time()), NA))
 POSIXlt[1:2], format: "2018-10-07 00:43:06" NA
> unclass(c(as.POSIXlt(Sys.time()), NA))
$sec
[1] 15.78872       NA

$min
[1] 43 NA

$hour
[1]  0 NA
# skipped a few rows

$isdst
[1]  1 -1

$zone
[1] "EEST" ""   
# skipped a few rows 

Короче говоря, POSIXlt представляет собой список векторов, каждый из которых представляет одну из единиц даты / времени: секунды, минуты, часы, дни и т. Д., А также часовой пояс и т. Д.не является методом для na.omit для POSIXlt, поэтому используется na.omit.default, который не знает особенностей класса POSIXlt и обрабатывает его как обычный список.

> na.omit(list(NA,NA,NA))
[[1]]
[1] NA

[[2]]
[1] NA

[[3]]
[1] NA

Если вам нужен na.omit метод для POSIXlt, вы можете написать один.Но если нет, то проще использовать POSIXct.

Следствие: na.omit на самом деле тоже не работает со списками (т. Е. Его можно использовать, но он ничего не делает).Вы можете sapply или lapply na.omit в списках, но это также даст странные результаты (NA компоненты будут заменены на logical(0)).Похоже, na.omit предназначено для использования с атомарными векторами или факторами, а также с фреймами данных.(Страница справки говорит, что это в основном полезно с фреймами данных).Это означает, что na.omit не предназначен для использования со списками, включая POSIXlt.

Наконец, зачем вообще использовать POSIXlt?Идея (насколько я понимаю) состоит в том, что вы можете легко манипулировать компонентами даты - но даже это может привести к неожиданным результатам:

> foo <- as.POSIXlt(Sys.time())
> foo
[1] "2018-10-07 01:06:22 EEST"
> foo$year
[1] 118
> foo$mon
[1] 9
> foo$mon <- 10
> foo
[1] "2018-11-07 01:06:22 EEST"
> foo$year <- 2018
> foo
[1] "3918-11-07 01:06:22 EEST"

Так что если вам нужно манипулировать компонентами даты отдельно, вы будетеесть меньше сюрпризов с lubridate.

> library(lubridate)
> year(foo)
[1] 3918
> year(foo) <- 2018
> foo
[1] "2018-11-07 01:06:22 EET"
> month(foo)
[1] 11
> month(foo)<-10
> foo
[1] "2018-10-07 01:06:22 EEST"
...