如何在R数据框中从混合格式日期提取年份(含Excel序列号)
问题:从多格式日期字段中提取年份,处理Excel日期序列号
我正在清理一个混乱的数据库,其中变量inicio包含多种日期输入格式,例如:"MAR 23"、"1º Sem 2021"、"OUT/21"、"41365",需要提取所有日期对应的年份。
已尝试的方法及问题
1. 正则提取函数
用正则提取末尾两位数字作为年份,代码如下:
# 提取末尾两位数字(仅年份) pattern <- "\\b\\d{2}$" # 正则提取年份的函数 extract_years <- function(text, pattern) { matches <- regmatches(text, gregexpr(pattern, text)) years <- sapply(matches, function(x) as.numeric(x)) return(years) } # 使用dplyr从日期列提取年份 informex_clean_2 <- informex_clean |> mutate(ano = extract_years(inicio, pattern))
该函数对"MAR 23"、"OUT/21"、"1º Sem 2021"这类格式有效,但对"41365"这类Excel日期序列号会返回NA。
2. 日期转换函数尝试
尝试写了转换函数,但对"41365"仍返回NA:
# 尝试转换为日期的自定义函数 convert_to_date_if_possible <- function(x) { if (is.numeric(x)) { # 若输入为数值,假设是日期表示并尝试转换 x_date <- as.Date(as.numeric(x), origin = "1899-12-30") # Excel日期原点为1899-12-30 if (!is.na(x_date)) { # 转换成功,返回日期对象 return(x_date) } else { # 转换失败,返回原始字符值 return(x) } } else { # 输入非数值,返回原始字符值 return(x) } }
问题核心:"41365"在数据中是字符类型,is.numeric(x)判断为FALSE,无法进入转换逻辑。
解决方案
下面是修正后的完整年份提取函数,能处理所有上述格式:
library(dplyr) library(lubridate) library(stringr) extract_year <- function(x) { # 处理Excel日期序列号(字符型转数值后转日期) num_x <- suppressWarnings(as.numeric(x)) if (!is.na(num_x)) { return(year(as.Date(num_x, origin = "1899-12-30"))) } # 提取4位完整年份(如"1º Sem 2021"中的2021) full_year <- suppressWarnings(as.numeric(str_extract(x, "\\b20\\d{2}\\b"))) if (!is.na(full_year)) { return(full_year) } # 提取两位年份并补全为4位(默认2000年后,可按需调整) two_digit <- suppressWarnings(as.numeric(str_extract(x, "\\b\\d{2}\\b"))) if (!is.na(two_digit)) { # 若需区分19xx/20xx,可加判断:two_digit > 50 则 1900 + two_digit,否则2000 + two_digit return(2000 + two_digit) } # 无匹配时返回NA return(NA_integer_) } # 应用到数据框 informex_clean_2 <- informex_clean |> mutate(ano = extract_year(inicio))
关键说明
- 先尝试将输入转为数值,解决字符型Excel序列号的转换问题;
- 优先提取4位年份,避免两位年份的歧义;
- 两位年份默认补2000,若数据包含19xx年份,可修改逻辑区分;
- 用
suppressWarnings()屏蔽转换失败的警告,不影响最终输出。
内容的提问来源于stack exchange,提问作者Paula Macedo
相关产品推荐
相关产品推荐

