【发布时间】:2018-01-29 18:47:04
【问题描述】:
回答这个问题Temperature curve in R 我遇到了dplyr::filter - lubridate::minute 组合的奇怪行为。
见下方测试数据dta。 dta$time 是 lubridate::hhmm 格式。
library(lubridate)
library(dplyr)
dta$Time <- hm(dta$Time)
要仅获取完整小时(即 0 分钟)的行,可以使用 lubridate::minute 进行子集化,如下所示:
dta[minute(dta$Time) == 0,]
# Time Temp1 Temp2
# 1 0S 18.62800 18.54458
# 7 1H 0M 0S 18.45733 18.22625
# 13 2H 0M 0S 18.33258 18.04142
但是,当使用dplyr的filter时,像这样
dta %>% filter(minute(Time) == 0)
# Time Temp1 Temp2
# 1 0S 18.62800 18.54458
# 2 10M 0S 18.45733 18.22625
# 3 20M 0S 18.33258 18.04142
结果并不符合预期。 (更新:Temp1 和 Temp2 的值是正确的,只有 Time 已损坏...感谢 @Brian btw 提供此提示。)
另外还会返回此警告:
Warning message: In format.data.frame(x, digits = digits, na.encode = FALSE) : corrupt data frame: columns will be truncated or padded with NAs
这也被报告并以某种方式解决了here,但只是通过强制,这似乎消除了 lubridate 的有趣(并且非常易读)部分。
问题:有没有办法(迄今为止)将dplyr::filter lubridate::hhmm(ss) 格式化而不强制转换为字符等?
更新:
似乎是由
创建的向量minute(dta$Time)
# [1] 0 10 20 30 40 50 0 10 20 30 40 50 0
看起来像一个数字向量,但似乎有一些神秘的特征。
此外,正如@Lyngbakr 指出的那样,即使与== 的比较也不具有作为“正常”逻辑向量的通常特征。
tst <- minute(dta$Time) == 0
dta %>% filter(tst)
会产生同样奇怪的Time 列。
样本数据:
dta <- read.table(text = " Time Temp1 Temp2
1 00:00 18.62800 18.54458
2 00:10 18.60025 18.48283
3 00:20 18.57250 18.36767
4 00:30 18.54667 18.36950
5 00:40 18.51483 18.36550
6 00:50 18.48325 18.34783
7 01:00 18.45733 18.22625
8 01:10 18.43767 18.19067
9 01:20 18.41583 18.22042
10 01:30 18.39608 18.21225
11 01:40 18.37625 18.18658
12 01:50 18.35633 18.05942
13 02:00 18.33258 18.04142", header = T)
【问题讨论】:
-
有趣。看来
filter无法处理Formal class 'Period'。如果您先收集并尝试过滤 (dta %>% gather(var, val, -Time) %>% filter(minute(Time) == 0)),则会引发错误Error in filter_impl(.data, quo) : Result must have length 26, not 13 -
我觉得特别奇怪的是,即使你使用中间变量,它仍然存在。例如,
tst <- minute(dta$Time) == 0,然后是dta %>% filter(tst)。据我所知,tst只是一个常规的逻辑向量。 -
所有列除了
Time都正确filtered。我尝试创建一个中间变量mutate(mins = minutes(Time))并对其进行过滤,并返回了正确的行,但不是Time列。