Превратить строку даты в количество дней в R - PullRequest
2 голосов
/ 16 мая 2019

У меня есть фрейм данных со столбцом, который представляет количество дней, называемых 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.Любая помощь приветствуется.спасибо

Ответы [ 3 ]

2 голосов
/ 16 мая 2019

Вот базовый подход R, использующий eval вместе с sub.Мы можем попробовать заменить 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
1 голос
/ 16 мая 2019

Дайте этому шанс:

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)))
1 голос
/ 16 мая 2019

Опция будет 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) ))

data

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))
...