【问题标题】:How do i convert my date values into year in r我如何将我的日期值转换为 r 中的年份
【发布时间】:2022-01-13 16:25:31
【问题描述】:

又是新的复杂的一天

以下是我作为输入的列和行:

ID  Age
123 23 Years 1 Month 2 Days
125 28 Years 9 Month 14 Days
126 28 years
127 34 YEAR
128 35 Years 8 Month 21 Days
129 38 Years 5 Month 25 Days
130 32.8

我需要在新列中每年计算它们,例如:

ID  Age                      Age_new
123 23 Years 1 Month 2 Days     23.1
125 28 Years 9 Month 14 Days    28.9
126 28 years                    28
127 34 YEAR                     34
128 35 Years 8 Month 21 Days    35.8
129 38 Years 5 Month 25 Days    38.5
130 32.8                        32.8

我尝试了 by stringr 包,但我只得到第一个字符串 不像上面那样提供。

【问题讨论】:

  • 没有完美的方法可以做到这一点:月份可以是 28、29、30 或 31 天,因此您显示的十进制年份是一个近似值。您是否假设一个月为30.41667 天长?那么闰年呢,你预计每月有30.5 天吗?我们如何知道使用哪个?
  • 如果小数点后的数字只是月数,您可能会遇到排序问题(例如 23 年零 11 个月 - 23.11 - 会在 23 年零 2 个月 - 23.2 - 如果是按数字或字符顺序排序)
  • 这样做的目的是什么,当我编写代码并将其粘贴到此处时,他们的数字年龄已经过时了。获取他们的出生日期。如果您知道获取数据的日期,您可以轻松地用您拥有的数据减去该日期作为自出生以来的持续时间。当您拥有 dob 时,您可以始终以准确的方式对其进行可视化。
  • 密切相关:Transforming complete age from character to numeric in R。应用my answer there,只需转换为小写,不带单位的值加上“年”:library(lubridate)time_length(period(sub("(^\\d+\\.?\\d*$)", "\\1 years", tolower(dat$Age))), unit = "years").

标签: r dplyr tidyverse


【解决方案1】:

这是一个粗略的近似值:

func <- function(x, ptn) {
  out <- gsub(paste0(".*?\\b([0-9.]+)\\s*", ptn, ".*"), "\\1", x, ignore.case = TRUE)
  ifelse(out == x, NA, out)
}

library(dplyr)
dat %>%
  mutate(
    data.frame(
      lapply(c(yr = "year", mon = "month", day = "day"),
             function(ptn) as.numeric(func(Age, ptn)))
    ),
    yr = if_else(is.na(yr), suppressWarnings(as.numeric(Age)), yr),
    across(c(yr, mon, day), ~ coalesce(., 0)), New_Age = yr + mon/12 + day/365
  )
#    ID                      Age   yr mon day  New_Age
# 1 123  23 Years 1 Month 2 Days 23.0   1   2 23.08881
# 2 125 28 Years 9 Month 14 Days 28.0   9  14 28.78836
# 3 126                 28 years 28.0   0   0 28.00000
# 4 127                  34 YEAR 34.0   0   0 34.00000
# 5 128 35 Years 8 Month 21 Days 35.0   8  21 35.72420
# 6 129 38 Years 5 Month 25 Days 38.0   5  25 38.48516
# 7 130                     32.8 32.8   0   0 32.80000

(我不保证真实的准确性。)


数据

dat <- structure(list(ID = c(123L, 125L, 126L, 127L, 128L, 129L, 130L), Age = c("23 Years 1 Month 2 Days", "28 Years 9 Month 14 Days", "28 years", "34 YEAR", "35 Years 8 Month 21 Days", "38 Years 5 Month 25 Days", "32.8")), class = "data.frame", row.names = c(NA, -7L))

【讨论】:

    【解决方案2】:

    这是我的方法。我总是尽量避免使用正则表达式,因为它对我来说太可怕了。如果您的数据像您的示例一样完全分开,我认为我的代码将起作用。我完全理解这不是最有效的方法。但是,嘿,它有效

    dat %>% 
      mutate(space_counter = stringr::str_count(Age," ")) %>% 
      tidyr::separate(Age,into = paste0("tmp_col_",1:(max(.$space_counter)+1)),sep = " ") %>% 
      select(ID, tmp_col_1,tmp_col_3,tmp_col_5) %>% 
      setNames(c("ID","year","month","day")) %>% 
      mutate(across(everything(), ~replace_na(.x, 0))) %>% 
      mutate_if(is.character,as.integer) %>% 
      mutate(asdur = as.duration(years(year) + months(month) + days(day))) %>% 
      mutate(age_new = as.numeric(asdur)/3.154e+7)
    

    输出:

    【讨论】:

      猜你喜欢
      • 2014-12-29
      • 1970-01-01
      • 1970-01-01
      • 2021-08-18
      • 2020-12-05
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 2015-07-27
      相关资源
      最近更新 更多