如何在自定义函数中应用 excel_numeric_to_date?

问题描述

我正在尝试将自定义函数应用于一列 excel 导入日期。

我应用下一个函数

library(janitor)

fun_excel_date <- function(x){
  if(is.numeric(x)){
  excel_numeric_to_date(as.numeric(
    as.character(x)
  ),date_system = "modern")}
  
  else {
    return(NA)
  }
  
}

do.call(rbind,lapply(some_dummy_dates$date,fun_excel_date))

控制台输出

#     [,1]
#[1,] 3967
#[2,] 7783
#[3,] 6028
#[4,] 4479

当应用于一个元素时,函数工作正常,说 excel_numeric_to_date(as.numeric(as.character(29536)),date_system = "modern"),因为它返回 "1980-11-11"

然而,当应用于整个列时,该函数返回一个无法解释的数字输出。 即使在函数内部将 x 参数更改为 x <- as.Date(x,origin="1899-12-30"),问题仍然存在。

数据

some_dummy_dates <-structure(list(date = c(29536,33352,31597,30048)),class = "data.frame",row.names = c(NA,-4L))

我在函数中遗漏了什么吗? 还有其他方法吗?

解决方法

Date 类在内部存储为整数。因此,如果我们想避免强制转换为整数,请使用 c

do.call(c,lapply(some_dummy_dates$date,fun_excel_date))
#[1] "1980-11-11" "1991-04-24" "1986-07-04" "1982-04-07"

此外,转换为 matrix 将删除 Date 类并将其更改为 integer

matrix(do.call(c,fun_excel_date)))
#     [,1]
#[1,] 3967
#[2,] 7783
#[3,] 6028
#[4,] 4479

如果我们想把它存储在一个对象中,要么存储为一个 vector 要么创建一个可以有属性的 data.frame/tibble/data.table

data.frame(Date = do.call(c,fun_excel_date)))
#     Date
#1 1980-11-11
#2 1991-04-24
#3 1986-07-04
#4 1982-04-07

或将函数与 rowwise

一起使用
library(dplyr)
some_dummy_dates %>%
   rowwise %>%
   mutate(Date = fun_excel_date(date)) %>%
   ungroup

OP 的函数使用未矢量化的 if/else,这就是它只需要一个元素并对其进行转换的原因。这可以通过模拟检查列是否为 numeric(在 across 内)然后通过应用 excel_numeric_to_date

创建/修改列来矢量化
library(janitor)
some_dummy_dates %>% 
    mutate(across(where(is.numeric),~ excel_numeric_to_date(.,date_system = 'modern'),.names = "{.col}_new"))
#   date   date_new
#1 29536 1980-11-11
#2 33352 1991-04-24
#3 31597 1986-07-04
#4 30048 1982-04-07