根据其他变量的函数创建新变量

时间:2018-01-23 16:59:58

标签: r function date dataframe

如何将列entires作为参数传递给函数,然后创建一个新列,它是另外两个函数的函数?例如,使用this出色的函数将日期添加到日期,并采用此示例数据框:

df <- structure(
  list(
date = structure(
  c(
    17135,
    17105,
    17105,
    17074,
    17286,
    17317,
    17317,
    17347,
    17105,
    17317
  ),
  class = "Date"
),
monthslater = c(10,
                11, 13, 14, 3, 3, 3, 3, 4, NA)
  ),
  .Names = c("date", "monthslater"),
  row.names = c(NA, 10L),
  class = "data.frame"
)

我想创建一个新列,我将列datemonthslater中的条目传递给函数add.months我会认为这样的东西会起作用:

df$newdate <- add.months(df$date, df$monthslater)

但事实并非如此。

该功能的完整代码是:

add.months <- function(date,n) seq(date, by = paste(n, "months"), length = 2)[2]

3 个答案:

答案 0 :(得分:6)

使用%m+%中的lubridate - 包:

library(lubridate)
df$newdate <- df$date %m+% months(df$monthslater)

给出:

> df
         date monthslater    newdate
1  2016-11-30          10 2017-09-30
2  2016-10-31          11 2017-09-30
3  2016-10-31          13 2017-11-30
4  2016-09-30          14 2017-11-30
5  2017-04-30           3 2017-07-30
6  2017-05-31           3 2017-08-31
7  2017-05-31           3 2017-08-31
8  2017-06-30           3 2017-09-30
9  2016-10-31           4 2017-02-28
10 2017-05-31           4 2017-09-30

以类似的方式,您还可以添加日期或年份:

df$newdate2 <- df$date %m+% days(df$monthslater)
df$newdate3 <- df$date %m+% years(df$monthslater)

给出:

> df
         date monthslater    newdate   newdate2   newdate3
1  2016-11-30          10 2017-09-30 2016-12-10 2026-11-30
2  2016-10-31          11 2017-09-30 2016-11-11 2027-10-31
3  2016-10-31          13 2017-11-30 2016-11-13 2029-10-31
4  2016-09-30          14 2017-11-30 2016-10-14 2030-09-30
5  2017-04-30           3 2017-07-30 2017-05-03 2020-04-30
6  2017-05-31           3 2017-08-31 2017-06-03 2020-05-31
7  2017-05-31           3 2017-08-31 2017-06-03 2020-05-31
8  2017-06-30           3 2017-09-30 2017-07-03 2020-06-30
9  2016-10-31           4 2017-02-28 2016-11-04 2020-10-31
10 2017-05-31           4 2017-09-30 2017-06-04 2021-05-31

答案 1 :(得分:1)

或者用基础R:

df$newdate <- mapply(add.months, df[[1]], df[[2]], SIMPLIFY = FALSE)

> df
         date monthslater    newdate
1  2016-11-30          10 2017-09-30
2  2016-10-31          11 2017-10-01
3  2016-10-31          13 2017-12-01
4  2016-09-30          14 2017-11-30
5  2017-04-30           3 2017-07-30
6  2017-05-31           3 2017-08-31
7  2017-05-31           3 2017-08-31
8  2017-06-30           3 2017-09-30
9  2016-10-31           4 2017-03-03
10 2017-05-31           4 2017-10-01

答案 2 :(得分:1)

对于您当前的特定问题,请考虑mapply将这两个向量元素传递到已定义的函数中。由于 monthslater 包含NA,因此请为定义的函数添加tryCatch

add.months <- function(date, n) {
  tryCatch(seq(date, by = paste(n, "months"), length = 2)[2],
           warning = function(w) return(NA),
           error = function(e) return(NA))
}

df$newdate <- as.Date(mapply(add.months, df$date, df$monthslater), origin="1970-01-01")
df

#          date monthslater    newdate
# 1  2016-11-30          10 2017-09-30
# 2  2016-10-31          11 2017-10-01
# 3  2016-10-31          13 2017-12-01
# 4  2016-09-30          14 2017-11-30
# 5  2017-04-30           3 2017-07-30
# 6  2017-05-31           3 2017-08-31
# 7  2017-05-31           3 2017-08-31
# 8  2017-06-30           3 2017-09-30
# 9  2016-10-31           4 2017-03-03
# 10 2017-05-31          NA       <NA>

另外,请注意涉及2月底的author's item,因此#9将提前3天延长。