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

使用tidyverse风格调用自定义日期函数后日期格式异常如何解决?

问题原因

你的fix_date_all函数用lapply处理日期向量后,返回的是列表类型。而mutate(across(...))期望接收向量类型的数据,当列表传入时,Date对象会被强制转换为底层的整数(即从1970-01-01开始计算的天数),这就是你看到那些奇怪数字的原因。

解决方案

方法1:修改原函数,返回向量而非列表

把函数里的lapply替换成能返回向量的函数,比如sapply或者purrr::map_vec:

# 修改后的fix_date_all
fix_date_all <- function(date){
  fix_date <- function(d) {
    if (nchar(d) != 8) d <- paste0("0", d)
    
    dd <- substr(d, 1,2)
    mm <- substr(d, 3,4)
    yyyy <- substr(d, 5,8)
    
    as.Date(paste0(dd, ".", mm, ".", yyyy), "%d.%m.%Y")
  }
  
  # 用sapply替换lapply,自动简化为向量
  sapply(date, fix_date)
}

# 现在用across调用就正常了
df %>% mutate(across(date, fix_date_all))

方法2:重写为向量化函数(更符合tidyverse风格)

直接写向量化的逻辑,避免嵌套循环,效率更高:

fix_date_vec <- function(date) {
  # 给不足8位的日期补前导0
  date_padded <- if_else(nchar(date) != 8, paste0("0", date), date)
  # 拆分日、月、年
  dd <- substr(date_padded, 1, 2)
  mm <- substr(date_padded, 3, 4)
  yyyy <- substr(date_padded, 5, 8)
  # 转换为Date类型
  as.Date(paste(dd, mm, yyyy, sep = "."), "%d.%m.%Y")
}

# 调用方式
df %>% mutate(across(date, fix_date_vec))

方法3:直接在mutate里写逻辑(更简洁)

如果不需要复用函数,也可以直接在mutate里完成转换:

df %>% 
  mutate(
    date = if_else(nchar(date) != 8, paste0("0", date), date) %>%
      {paste(substr(.,1,2), substr(.,3,4), substr(.,5,8), sep=".")} %>%
      as.Date("%d.%m.%Y")
  )
验证结果

以上三种方法运行后,都会得到正确的Date格式列:

date x1 x2
1 2016-10-18  1  1
2 2017-10-11  2  1
3 2017-05-04  3  1
4 2018-10-18  4  1
5 2018-10-03  5  1

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 19:25:29