【问题标题】:Turn date string to number of days in R将日期字符串转换为 R 中的天数
【发布时间】:2019-10-03 05:08:31
【问题描述】:

我有一个数据框,其中有一列表示称为 num_days 的天数为“0”、“”、“0xY0xM”、“0xM”,我想将其更改为天数。

这就是数据框的样子

| a | b | num_days | d  |
| 2 | 3 | '01Y'    | 99 |
| 2 | 4 |  ""      |  8 |
| 3 | 7 | "01Y02M" | 7  |
| 4 | 1 |  "0"     | 8  |

Y 代表每年 365 天,每个月代表 30 天

| a | b | num_days | d  |
| 2 | 3 |   365    | 99 |
| 2 | 4 |   0      |  8 |
| 3 | 7 |   425    | 7  |
| 4 | 1 |   0      | 8  |

目前这是解决方案:

return_days <- function(x){
  if(x == ""){
      return(0)
  }
  d = gsub("Y", ".", x=x, ignore.case=FALSE, fixed=TRUE)
  d = gsub("M", "" , x=d, ignore.case=FALSE, fixed=TRUE)
  d = strsplit(d, '[.]')
  return( ifelse(length(d[[1]]) == 1, 30*as.numeric(x[[1]][1]), 30* as.numeric(d[[1]][1]) + 365*as.numeric(d[[1]][2]) ) ) 
}

我相信这可以写得更好,不幸的是我还不是 R 向导。任何帮助表示赞赏。谢谢

【问题讨论】:

    标签: r string function dataframe gsub


    【解决方案1】:

    一个选项是gsubfn

    library(gsubfn)
    i1 <- !df1$num_days  %in% c("", 0)
    df1$num_days[i1] <-sapply(gsub("\\+$", "", gsubfn("[A-Z]", 
           list(Y= '*365+', M = '*30'),
           df1$num_days[i1])), function(x) eval(parse(text = x)))
    

    或使用tidyverse

    library(tidyverse)
    df1 %>% 
       mutate(num_days = case_when(str_detect(num_days, "Y|M") ~ 
        as.numeric(str_extract(num_days, "\\d+(?=Y)") ) * 365 + 
            replace_na(as.numeric(str_extract(num_days, "\\d+(?=M)")) * 30, 0), 
         TRUE ~ as.numeric(num_days) ))
    

    数据

    df1 <- structure(list(a = c(2L, 2L, 3L, 4L), b = c(3L, 4L, 7L, 1L), 
        num_days = c("01Y", "", "01Y02M", "0"), d = c(99L, 8L, 7L, 
        8L)), class = "data.frame", row.names = c(NA, -4L))
    

    【讨论】:

      【解决方案2】:

      试一试:

      ifelse(substring(df$num_days, 3, 3) == "Y",
             365 * as.numeric(substring(df$num_days, 1, 2)) +
                 30 * as.numeric(substring(df$num_days, 4, 5)),
             30 * as.numeric(substring(df$num_days, 1, 2)))
      

      【讨论】:

        【解决方案3】:

        这是使用evalsub 的基本R 方法。我们可以尝试将Y 替换为*365,将M 替换为*30。这会生成文字算术表达式,其值为天数。然后,我们可以使用eval() 来评估该表达式。

        input <- "01Y02M"
        input <- sub("Y", "*365+", input)
        input <- sub("M", "*30+", input)
        input <- sub("\\+$", "", input)
        input
        eval(parse(text=input))
        
        [1] "01*365+02*30"
        [1] 425
        

        【讨论】:

          猜你喜欢
          • 2016-07-19
          • 2023-03-26
          • 2021-03-14
          • 2023-03-21
          • 2019-06-22
          • 2020-11-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多