问题描述
我正在尝试将自定义函数应用于一列 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