我的问题与 this (closed) lubridate issue 有关,但更普遍地与 R 中的 for 循环有关:
library(lubridate)
dates=c(ymd("20180501"), ymd("20180502"), ymd("20180503"))
print(dates)
# [1] "2018-05-01" "2018-05-02" "2018-05-03"
# ... as expected
print(dates[1])
# [1] "2018-05-01"
# ... as expected
for(d in dates) print(d)
# [1] 17652
# [1] 17653
# [1] 17654
# ... unexpected!
当遍历
dates
时,R默默地将dates
的元素转换为数字,因此失去了所有的日期性。这是出乎意料的,会导致错误,例如当打印日期并期待“2018-05-01”时,却得到一个整数。
github issue中lubridate dev的回复是
in
中的运算符是“原始的”,不会将日期时间向量分解为日期时间。所以 x 是令人惊讶的“数字”。for (x in dates)
他们建议改用
purrr::map
或for (i in seq_along(dates))
。当然在上面的例子中 map(dates, print)
更简洁并且可能更可取,但有些情况下有人可能更喜欢使用 for 循环来迭代日期向量。
我想知道应该在哪里以及如何捕获与此行为相关的错误:
for (i in seq_along(dates)) d = dates[i] ...
的习惯吗?for ... in
默默地转换我的数据?in
运算符来解决这里的问题吗?我不建议您这样做,但您可以更改 for 循环来解决这个问题(至少在您自己的代码中)。
就像 R 中的几乎所有其他操作一样,
for
循环被实现为一个函数。在这种情况下,for
是保留字,因此您需要使用反引号来引用它,但您可以定义自己的函数来替换标准函数。
例如:
myfor <- function(var, seq, expr ) {
var <- deparse(substitute(var))
`for` <- base::`for`
for (i in seq_along(seq)) {
assign(var, seq[i], envir = parent.frame())
eval(substitute(expr), envir = parent.frame())
}
`for` <- myfor
invisible(NULL)
}
`for` <- myfor
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
dates=c(ymd("20180501"), ymd("20180502"), ymd("20180503"))
for(d in dates) print(d)
#> [1] "2018-05-01"
#> [1] "2018-05-02"
#> [1] "2018-05-03"
创建于 2023-02-24 与 reprex v2.0.2
我不保证我得到了这里的环境,所以使用风险自负!
关于你的问题:我想其他人已经回答了Q1 - Q3。关于 Q4:是的,他们当然可以,但我敢肯定他们不会,因为这个函数比标准的 for 循环慢得多。