drop_na( ) 无法在 POSIX-lt object 上工作
drop_na( ) cannot work on POSIX-lt object
根据标题,我做了一个简单的例子来测试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()
识别吗?
简答:除非你真的需要 POSIXlt
,否则请使用 POSIXct
更长的答案:
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 是一个向量列表,每个向量代表一个 date/time 单位:秒、分钟、小时、天等,还有时区等。没有方法na.omit
用于 POSIXlt,因此使用 na.omit.default
,它不知道 POSIXlt
class 的具体情况并将其视为普通列表。
> na.omit(list(NA,NA,NA))
[[1]]
[1] NA
[[2]]
[1] NA
[[3]]
[1] NA
如果你需要POSIXlt
的na.omit
方法,你可以写一个。但如果不是真的,使用 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"
根据标题,我做了一个简单的例子来测试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()
识别吗?
简答:除非你真的需要 POSIXlt
,否则请使用 POSIXct更长的答案:
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 是一个向量列表,每个向量代表一个 date/time 单位:秒、分钟、小时、天等,还有时区等。没有方法na.omit
用于 POSIXlt,因此使用 na.omit.default
,它不知道 POSIXlt
class 的具体情况并将其视为普通列表。
> na.omit(list(NA,NA,NA))
[[1]]
[1] NA
[[2]]
[1] NA
[[3]]
[1] NA
如果你需要POSIXlt
的na.omit
方法,你可以写一个。但如果不是真的,使用 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"