r - 如何将特定(动态)列的日期增加一年?

标签 r loops date lapply na

我不断遇到“字符串不是标准明确格式”错误。

  • 我有多个数据帧(接近 100 个),其中包含多个不同的“日期”列,其中包括一些称为“期间”的列...这些列的格式略有不同
  • 目标是快速迭代数据帧,识别任何“Period”“Date”列,并将日期值增加 1 年。
  • “Period”“Date” 列中的某些值可能为空/缺失
  • 这需要是动态的,以防 future 将另一个“日期”列添加到数据帧之一

这是我正在解决的问题的简化版本:

grp = c("A","A","A","A","A","A","A")
Period =c('','','201901','201901','201902','201902','201903')
Date_Begin = c('','','2019-01-31','2019-01-13','2019-02-01','2019-02-01','2019-03-25')
Date_End = c('','','2019-03-31','2019-04-25','2019-03-01','2019-06-30','2019-07-25')
col4X = c(0,0,"",1.5,1.75,1,NA)
col5Y = c(2,2,2,2,2,2,2)

df1x =  data.frame(grp,Period,Date_Begin,Date_End,col4X,col5Y)


grp = c("A","A","A","A","A","A","A")
Period =c('','','201904','201904','201907','201907','201908')
Date_Start = c('','','2019-04-30','2019-01-13','2019-02-01','2019-02-01','2019-03-25')
Date_End = c('','','2019-07-31','2019-04-25','2019-03-11','2019-06-25','2019-07-20')
Expected_Date = c('','','2019-02-28','2019-06-25','2019-03-06','2019-06-25','2019-07-20')
col4X = c(0,0,"",1.5,1.75,1,NA)
col5Y = c(2,2,2,2,2,2,2)

df2x =  data.frame(grp,Period,Date_Start,Date_End,Expected_Date,col4X,col5Y)

df_list <- list(df1x, df2x)



rep_fun <- function(df){
  mutate(df, across(matches("Date"), ~ as.Date(.) + 365),
         across(matches("Period"), ~ (as.Date(paste0(., "01"), "%Y%m%d") + 365) %>% format("%Y%m")))
}

lapply(df_list, function(x) rep_fun(x))

最佳答案

在我看来,处理奇怪格式的日期的最佳方法是将它们转换为带有 as.Date 的日期,执行您需要执行的任何操作,然后将其转换回原始格式使用 format 进行格式化。您可以按照这个原则构建一个基本的 R 函数,但我的答案使用 dplyr

rep_fun <- function(df){
  mutate(df, across(matches("Date"), ~ as.Date(.) + 365),
         across(matches("Period"), ~ (as.Date(paste0(., "01"), "%Y%m%d") + 365) %>% format("%Y%m")))
}

我们正在更改名称中包含“日期”的每一列,将其转换为日期,并添加 365 天。然后我们改变 "Period" 列,添加一天 "01",将其转换为日期(指定格式 "%Y%m%d"),添加 365 天,并将其格式化回旧格式。

您还可以使用 lubridate 包并将 + 365 更改为 +years(1),这样无论经过多少天,年份都会增加一年。

您的示例中有一些奇怪的日期,例如 '2019-02-31',但它不存在。这是故意的吗?代码需要处理这个问题吗?因为我的没有。我将这些日期更改为运行该示例的现有日期。

结果:

> lapply(df_list, function(x) rep_fun(x))
[[1]]
  grp Period Date_Begin   Date_End col4X col5Y
1   A   <NA>       <NA>       <NA>     0     2
2   A   <NA>       <NA>       <NA>     0     2
3   A 202001 2020-01-31 2020-03-30           2
4   A 202001 2020-01-13 2020-04-24   1.5     2
5   A 202002 2020-02-01 2020-02-29  1.75     2
6   A 202002 2020-02-01 2020-06-29     1     2
7   A 202003 2020-03-24 2020-07-24  <NA>     2

[[2]]
  grp Period Date_Start   Date_End Expected_Date col4X col5Y
1   A   <NA>       <NA>       <NA>          <NA>     0     2
2   A   <NA>       <NA>       <NA>          <NA>     0     2
3   A 202004 2020-04-29 2020-07-30    2020-02-28           2
4   A 202004 2020-01-13 2020-04-24    2020-06-24   1.5     2
5   A 202007 2020-02-01 2020-03-10    2020-03-05  1.75     2
6   A 202007 2020-02-01 2020-06-24    2020-06-24     1     2
7   A 202008 2020-03-24 2020-07-19    2020-07-19  <NA>     2

更改的虚拟数据(没有不可能的日期):

grp = c("A","A","A","A","A","A","A")
Period =c('','','201901','201901','201902','201902','201903')
Date_Begin = c('','','2019-01-31','2019-01-13','2019-02-01','2019-02-01','2019-03-25')
Date_End = c('','','2019-03-31','2019-04-25','2019-03-01','2019-06-30','2019-07-25')
col4X = c(0,0,"",1.5,1.75,1,NA)
col5Y = c(2,2,2,2,2,2,2)

df1x =  data.frame(grp,Period,Date_Begin,Date_End,col4X,col5Y)


grp = c("A","A","A","A","A","A","A")
Period =c('','','201904','201904','201907','201907','201908')
Date_Start = c('','','2019-04-30','2019-01-13','2019-02-01','2019-02-01','2019-03-25')
Date_End = c('','','2019-07-31','2019-04-25','2019-03-11','2019-06-25','2019-07-20')
Expected_Date = c('','','2019-02-28','2019-06-25','2019-03-06','2019-06-25','2019-07-20')
col4X = c(0,0,"",1.5,1.75,1,NA)
col5Y = c(2,2,2,2,2,2,2)

df2x =  data.frame(grp,Period,Date_Start,Date_End,Expected_Date,col4X,col5Y)

df_list <- list(df1x, df2x)

session 信息:

R version 4.2.0 (2022-04-22 ucrt)

locale:
LC_COLLATE=Portuguese_Brazil.utf8
LC_CTYPE=Portuguese_Brazil.utf8                     
LC_TIME=Portuguese_Brazil.utf8

other attached packages:
dplyr_1.0.9

关于r - 如何将特定(动态)列的日期增加一年?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74541361/

相关文章:

c - 使用哪个循环?

ios - 从 weekOfYear 获取不正确的开始和结束日期

mysql 检查日期是否大于 0000-00-00

r - 在 ggplot 中使用多层美学

R ggplot : Change spacing between two different legends

r - 使用 rCharts hPlot 显示多个时间序列

java - 将嵌套 for 循环编写为 while

javascript - 迭代遍历嵌套对象中的所有节点(不使用递归)

r - 为什么插入符号火车占用这么多内存?

java - 如何从字符串日期中检索分钟?