如何简化dplyr / apply脚本?

时间:2018-02-11 15:39:24

标签: r dplyr posixct coding-efficiency

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

基本上,数据框中有三列具有不同的日期。需要实现以下目标:

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

  2. 计算列/行中的实际时间与名义日期/时间组合之间的时间差,该组合产生三个具有秒数的新列

  3. 我已经成功完成了这项工作,但我的答案(我已经寻求帮助)似乎太长而且繁琐,这就是:

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

    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)
    

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

1 个答案:

答案 0 :(得分:2)

以下是您所描述问题的解决方案:

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))