You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在R中用across()为后缀_date的日期列批量叠加xdays值

问题:使用across()批量处理后缀为_date的列,叠加xdays列数值生成新日期列

输入示例(df)

id xdays curation_date event_date
1  1    -4    2024-09-01 2024-07-04
2  2    10    2024-07-24 2024-06-13
3  3     7    2024-01-03 2023-12-03

预期输出(df1)

id xdays curation_date event_date manual_shift_curation_date manual_shift_event_date
1  1    -4    2024-09-01 2024-07-04                 2024-08-28              2024-06-30
2  2    10    2024-07-24 2024-06-13                 2024-08-03              2024-06-23
3  3     7    2024-01-03 2023-12-03                 2024-01-10              2023-12-10

尝试的代码及错误

手动实现的代码可正常运行,但使用自定义函数结合across()的多种写法均报错:

#requirement - #add the value of df$xdays to any column that is named as a date (and output the result as a date)
library(tidyverse)

################functions attempted
# 1) include a parameter for the column with the date shift
dateshift <- function(x,shiftcolumn) {as.Date(as.Date(x) + {{shiftcolumn}})} #shiftcolumn is actually a constant, but this is closest to working.
# or
# 2) just call the dateshift column within the function
dateshift_nocol <- function(x) {as.Date(as.Date(x) + {{xdays}})}  

#example dataframe
df <- data.frame(id=c(1,2,3), 
                 xdays=c(-4, 10, 7),
                 curation_date=c('2024-09-01','2024-07-24','2024-01-03'),
                 event_date=c('2024-07-04','2024-06-13','2023-12-03')
)

###############manaully shift date to show expected results
df1 <- df %>% 
  mutate(manual_shift_curation_date=as.Date(as.Date(curation_date)+xdays),
         manual_shift_event_date  =as.Date(as.Date(event_date)+xdays))
#works

###############using dateshift passing the constant column as a parameter
df2 <- df %>%
  mutate(across(matches("date"), dateshift(.,shiftcolumn=xdays), .names = "shifted_{.col}")) #renamed for qc check
#error: Caused by error in `as.Date.default()`:! do not know how to convert 'x' to class “Date”

df3 <- df %>% 
  mutate(across(matches("date"), ~ apply(., 1, dateshift))) 
#error: Caused by error in `apply()`:! dim(X) must have a positive length

###################using dateshift_nocol (without passing the constant column value)
df4 <- df %>%
  mutate(across(matches("date"), dateshift_nocol, .names = "shifted_{.col}")) #renamed for qc check
# Caused by error in `across()`:! Can't compute column `shifted_curation_date`. Caused by error: ! object 'xdays' not found

df5 <- df %>% 
  mutate(across(matches("date"), ~ apply(., 1, dateshift_nocol)))
#error: Caused by error in `apply()`:! dim(X) must have a positive length

解决方案

方法1:直接在across()中使用lambda表达式(无需自定义函数)

这是最简洁的实现方式,避免函数作用域问题:

df_result <- df %>%
  mutate(across(ends_with("_date"), 
                ~ as.Date(as.Date(.x) + xdays), 
                .names = "manual_shift_{.col}"))
  • 用ends_with("_date")精准匹配后缀为_date的列
  • ~定义lambda函数,.x代表当前处理的日期列,xdays可直接引用数据框内的列

方法2:修正自定义函数的参数传递

若需保留自定义函数,可通过两种方式修复:

方式A:使用.data代词明确作用域

dateshift <- function(x) {
  as.Date(as.Date(x) + .data$xdays)
}

df_result <- df %>%
  mutate(across(ends_with("_date"), dateshift, .names = "manual_shift_{.col}"))

方式B:显式传递xdays参数

dateshift <- function(x, shift_col) {
  as.Date(as.Date(x) + shift_col)
}

df_result <- df %>%
  mutate(across(ends_with("_date"), 
                ~ dateshift(.x, shift_col = xdays), 
                .names = "manual_shift_{.col}"))

错误原因解析

  • df2错误:直接调用dateshift(.,shiftcolumn=xdays)会把整个数据框传给x参数,而非当前处理的列,需用lambda函数传递单个列
  • df3/df5错误:apply用于矩阵/数组处理,而across处理的是向量列,日期向量加数值向量本身就是逐行运算,无需额外嵌套apply
  • df4错误:自定义函数dateshift_nocol中的{{xdays}}无法找到数据框内的xdays,函数不在数据框作用域内,需用.data代词或显式传参

内容的提问来源于stack exchange,提问作者Lauren Gigliotti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 14:37:20