如何将数据框的info字符串列拆分为年、月、日列?
问题描述
现有如下数据集,其中info列包含类似PRISM_ppt_provisional_4kmD2_20220925_bil的字符串,需要将该列拆分为year(年)、month(月)、day(日)列:
df = structure(list(id = c(1, 2, 3, 4, 5, 6, 7, 8), info = c("PRISM_ppt_provisional_4kmD2_20220925_bil", "PRISM_ppt_provisional_4kmD2_20220926_bil", "PRISM_ppt_provisional_4kmD2_20220927_bil", "PRISM_ppt_provisional_4kmD2_20220928_bil", "PRISM_ppt_provisional_4kmD2_20220929_bil", "PRISM_ppt_provisional_4kmD2_20220930_bil", "PRISM_ppt_provisional_4kmD2_20220925_bil", "PRISM_ppt_provisional_4kmD2_20220926_bil")), class = "data.frame", row.names = c(NA, -8L))
期望得到的结果如下:
desired_df = structure(list(id = c(1, 2, 3, 4, 5, 6, 7, 8), info = c("PRISM_ppt_provisional_4kmD2_20220925_bil", "PRISM_ppt_provisional_4kmD2_20220926_bil", "PRISM_ppt_provisional_4kmD2_20220927_bil", "PRISM_ppt_provisional_4kmD2_20220928_bil", "PRISM_ppt_provisional_4kmD2_20220929_bil", "PRISM_ppt_provisional_4kmD2_20220930_bil", "PRISM_ppt_provisional_4kmD2_20220925_bil", "PRISM_ppt_provisional_4kmD2_20220926_bil"), year = c(2022, 2022, 2022, 2022, 2022, 2022, 2022, 2022), month = c(9, 9, 9, 9, 9, 9, 9, 9), day = c(25, 26, 27, 28, 29, 30, 25, 26)), class = "data.frame", row.names = c(NA, -8L))
尝试用separate函数但不知道sep参数该如何设置:
# Extract year, month and day from info column df = separate(df, info, into = c("year", "month", "day"), sep = ?, convert = T)
解决方案
因为info列中的日期是连续的8位数字(格式为YYYYMMDD),没有明确分隔符,所以需要先提取出这部分日期字符串,再拆分为年、月、日。以下是几种可行的方法:
方法1:使用separate结合正则表达式
可以先提取日期部分再拆分,同时保留原info列:
library(tidyr) library(stringr) df <- df %>% mutate(date_str = str_extract(info, "\\d{8}")) %>% separate(date_str, into = c("year", "month", "day"), sep = c(4, 6), convert = TRUE)
也可以直接在separate中用正则定位拆分位置,忽略非日期部分:
df <- separate(df, info, into = c("drop", "year", "month", "day", "drop2"), sep = c(".*_(?=\\d{4})", 4, 2), convert = TRUE, remove = FALSE) %>% select(-drop, -drop2)
方法2:使用lubridate规范处理日期
借助lubridate包将日期字符串转为标准日期格式,再提取年、月、日:
library(tidyr) library(lubridate) library(stringr) df <- df %>% mutate(date = ymd(str_extract(info, "\\d{8}")), year = year(date), month = month(date), day = day(date)) %>% select(-date) # 不需要date列可删除该行
方法3:基础R字符串操作
如果不想加载额外包,用基础R函数即可完成:
# 提取8位日期字符串 date_str <- substr(df$info, nchar(df$info)-12, nchar(df$info)-5) # 拆分年、月、日并转为数值型 df$year <- as.integer(substr(date_str, 1, 4)) df$month <- as.integer(substr(date_str, 5, 6)) df$day <- as.integer(substr(date_str, 7, 8))
内容的提问来源于stack exchange,提问作者Ed_Gravy
相关产品推荐
相关产品推荐

