【问题标题】:How can I simplify my dplyr/apply script?如何简化我的 dplyr/apply 脚本?
【发布时间】:2018-02-11 15:39:23
【问题描述】:

我想使用包含 POSIXct 数据点的 df 完成几个步骤。

基本上,数据框中的三列具有不同的日期。需要达到以下几点:

  1. 将三列中每一行的所有日期更改为相同(保持时间不变

  2. 计算列/行中的实际时间与标称日期/时间组合之间的时间差,这会产生三个新列(秒)

我已经成功地做到了,但是我的答案(我已经寻求帮助)似乎太长太麻烦了,这里是:

我做的第一件事是创建一个用于计算的名义日期:

date.zero<- as.POSIXct("2018-01-01 00:00:00 EST")

然后我将特定列中数据框每一行中的所有日期更改为相同的日期

df$tim.col.1 <- as.POSIXct(sub("\\S+", "2018-01-01", df$tim.col.1))
df$tim.col.2 <- as.POSIXct(sub("\\S+", "2018-01-01", df$tim.col.2))
df$tim.col.2 <- as.POSIXct(sub("\\S+", "2018-01-01", df$tim.col.2))

最后,我使用 lapply 从 date.zero 中减去日期以产生以秒为单位的时差(即基本上从 00:00:00 开始的秒数)

df["tim.col.1"] <- lapply(df["tim.col.1"],function(x) x-date.zero)
df["tim.col.2"] <- lapply(df["tim.col.2"],function(x) x-date.zero)
df["tim.col.3"] <- lapply(df["tim.col.3"],function(x) x-date.zero)

现在。我猜所有这些都可以很容易地使用 lapply 以更好的方式或使用 dplyr 来完成,所以我不需要输入所有这些代码......也许使用类似的东西但是将所有东西集成在一起?

newdf  <- df %>% rowwise () %>% mutate(xxx=tim.col.1-date.zero,
                                  xxx2=tim.col.2-date.zero,
                                  xxx3=tim.col.3-date.zero)

有人可以告诉我如何最简洁有效地实现这一点。

【问题讨论】:

  • 我投票决定将此问题作为离题结束,因为要求改进工作代码的问题属于 Code Review,而不是 Stack Overflow。

标签: r dplyr posixct coding-efficiency


【解决方案1】:

这是您描述的问题的 dplyr 解决方案:

library(magrittr)
library(dplyr)
library(stringr)
library(lubridate)

date.zero<- ymd_hms("2018-01-01 00:00:00", tz = "America/New_York")

new_df <- df %>% # 1) change all dates to be the same for each row of the three columns
    mutate(tim.col.1 = ymd_hms(str_replace(tim.col.1, "\\S+", "2018-01-01"), tz = "America/New_York"),
          tim.col.2 = ymd_hms(str_replace(tim.col.2, "\\S+", "2018-01-01"), tz = "America/New_York"),
          tim.col.3 = ymd_hms(str_replace(tim.col.3, "\\S+", "2018-01-01"), tz = "America/New_York")) %>%
    # 2) calculate difference in time between actual time in the column/row against a 
    # nominal date/time combination which yields three new columns with seconds
    mutate(tim.col.1 = tim.col.1 - date.zero,
           tim.col.2 = tim.col.2 - date.zero,
           tim.col.3 = tim.col.3 - date.zero)

编辑:这里是基于 Moody_Mudskipper 建议的 mutate_if 版本:

new_df <- df %>% # 1) change all dates to be the same for each row of the three columns
    mutate_if(is.POSIXct, funs(ymd_hms(str_replace(., "\\S+", "2018-01-01"), tz = "America/New_York"))) %>%
    # 2) calculate difference in time between actual time in the column/row against a 
    # nominal date/time combination which yields three new columns with seconds
    mutate_if(is.POSIXct, funs(. - date.zero))

【讨论】:

  • 如果您要在多个列上应用相同的函数,可以使用 mutate_at 或 mutate_all
  • 谢谢。第二个似乎工作正常,并且在写作方面很吝啬。但是,您能否解释一下:ymd_hms(str_replace(.,我很难理解它。这段时间在做什么,为什么需要这个位。对不起我的无知:)
  • lubridate 包中的 ymd_hms 将值转换为年-月-日_小时-分钟-秒格式。 str_replace 函数将查看给定的字符向量,并将任何与正则表达式“\\S+”匹配的内容替换为指定的替换“2018-01-01”。这 '。'在 str_replace 函数中指定运行替换的向量将是 mutate_if() 传递的每一列中的数据。基本上,我们将每个 POSIXct 列传递给 str_replace 函数,然后将输出格式化为日期而不是字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-08-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多