【问题标题】:How to split epochs into year, month, etc如何将纪元拆分为年、月等
【发布时间】:2016-09-04 06:26:47
【问题描述】:

我有一个包含许多时间列的数据框。我想为年、月、日等每次添加列。

这是我目前所拥有的:

library(dplyr)
library(lubridate)

times <- c(133456789, 143456789, 144456789 ) 
train2 <- data.frame(sent_time = times, open_time = times)

time_col_names <- c("sent_time", "open_time")
dt_part_names <- c("year", "month", "hour", "wday", "day")

train3 <- as.data.frame(train2)

dummy <- lapply(time_col_names, function(col_name) { 
  pct_times <- as.POSIXct(train3[,col_name], origin = "1970-01-01", tz = "GMT")
  lapply(dt_part_names, function(part_name) {
    part_col_name <- paste(col_name, part_name, sep = "_")
    train3[, part_col_name] <- rep(NA, nrow(train3))
    train3[, part_col_name] <- factor(get(part_name)(pct_times))
  })
})

似乎一切正常,除了列从未被创建或分配。组件确实被提取,并且分配成功且没有错误,但 train3 没有任何新列。

当我在嵌套的 lapply 上下文之外调用它时,我检查了该分配是否有效:

train3[, "x"] <- rep(NA, nrow(train3))

在这种情况下,确实会创建列 x。

【问题讨论】:

  • @akrun - 定义 train2 并清理代码以最小化重现

标签: r dplyr lapply lubridate


【解决方案1】:

for 循环相比,通常认为apply 系列在性能方面具有优势。但for 循环与*apply() 系列循环之间最重要的区别在于后者设计为没有副作用

没有副作用有利于开发干净、结构良好且简洁的代码。如果一个人希望产生副作用,就会出现问题,这通常是代码设计有缺陷的症状。

这里有一个简单的例子来说明这一点

myvector <- 10:1
sapply(myvector,prod,2)
# [1] 20 18 16 14 12 10  8  6  4  2

看起来是正确的,对吧? sapply() 循环似乎将 myvec 的条目乘以 2(当然,这个结果本可以更容易实现,但这只是讨论 *apply() 功能的一个简单示例)。

然而,经过检查,我们发现这个操作根本没有改变myvector

> myvector
# [1] 10  9  8  7  6  5  4  3  2  1

那是因为sapply() 没有修改myvector副作用。在此示例中,sapply() 循环等效于命令print(myvector*2),而不是myvector &lt;- myvector * 2*apply() 循环返回一个对象,但它们不会修改原始对象。

如果真的想改变循环内的对象,超赋值运算符&lt;&lt;-是必要的,以修改循环范围外的对象。这几乎不应该这样做,在这种情况下,事情会变得非常丑。例如,下面的循环确实改变了我的myvector

sapply(seq_along(myvector), function(x) myvector[x] <<- myvector[x]*2)
> myvector
# [1] 20 18 16 14 12 10  8  6  4  2

R 中的编码不应该是这样的。请注意,同样在这种更复杂的情况下,如果使用普通赋值运算符 &lt;- 而不是 &lt;&lt;-,则 myvector 保持不变。正确的做法是分配*apply返回的对象,而不是在循环中修改它。

在 OP 描述的特定情况下,如果循环中的命令正确,变量 dummy 可能包含所需的输出。但是不能指望对象train3 在循环内被修改。为此,&lt;&lt;- 运算符是必需的。

fortunes::fortune(212) 中提到的一句话可能概括了这个问题:

基本上,R 不愿意让你朝自己的脚开枪,除非 你真的下定决心要这样做。 -- 比尔·维纳布尔斯

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 2022-10-13
    • 2019-08-18
    • 1970-01-01
    • 2015-03-17
    相关资源
    最近更新 更多