R语言 应用函数后如何维护日期格式

j0pj023g  于 2023-02-10  发布在  其他
关注(0)|答案(4)|浏览(91)

我有一个日期信息格式不正确的 Dataframe 。

date = c("18102016", "11102017", "4052017", "18102018", "3102018")
df <- data.frame(date = date, x1 = 1:5, x2 = rep(1,5))

我已经编写了函数fix_date_all(),当应用于向量df$date时,该函数会执行正确的格式设置

fix_date_all<- function(date){
  fix_date <- function(d) {
    if (nchar(d) != 8) d <- paste0("0", d)
    
    dd <- d %>% substr(1,2)
    mm <- d %>% substr(3,4)
    yyyy <- d %>% substr(5,8)
    
    d <- paste0(dd, ".", mm, ".", yyyy) %>% as.Date("%d.%m.%Y")
    
    d
  }
  
  lapply(date, fix_date)
}

fix_date_all(df$date)

现在,我想使用tidyverse样式将此变量转换为适当的日期格式:

df %>% mutate(across(date, fix_date_all))

然而,当使用它在tidyverse风格,日期得到搞砸了。

date x1 x2
1 17092  1  1
2 17450  2  1
3 17290  3  1
4 17822  4  1
5 17807  5  1
cidc1ykv

cidc1ykv1#

第二种选择是去掉lapply,并使用string::str_pad等重写函数:

library(dplyr, warn.conflicts = FALSE)

fix_date_all<- function(date){
  date %>%  
    stringr::str_pad(width = 8, pad = "0") %>% 
    as.Date(format = "%d%m%Y")
}

fix_date_all(df$date)
#> [1] "2016-10-18" "2017-10-11" "2017-05-04" "2018-10-18" "2018-10-03"

df %>% 
  mutate(across(date, fix_date_all))
#>         date x1 x2
#> 1 2016-10-18  1  1
#> 2 2017-10-11  2  1
#> 3 2017-05-04  3  1
#> 4 2018-10-18  4  1
#> 5 2018-10-03  5  1
hfsqlsce

hfsqlsce2#

输出是来自lapply调用的list

fix_date_all(df$date)
[[1]]
[1] "2016-10-18"

[[2]]
[1] "2017-10-11"

[[3]]
[1] "2017-05-04"

[[4]]
[1] "2018-10-18"

[[5]]
[1] "2018-10-03"

我们需要用c将其展平

library(dplyr)
df %>% 
   mutate(date = fix_date_all(date) %>%
   do.call(c, .))
  • 输出
date x1 x2
1 2016-10-18  1  1
2 2017-10-11  2  1
3 2017-05-04  3  1
4 2018-10-18  4  1
5 2018-10-03  5  1

或者在purrr的较新版本中,使用list_c

library(purrr)
df %>% 
    mutate(date = fix_date_all(date)  %>% list_c)
        date x1 x2
1 2016-10-18  1  1
2 2017-10-11  2  1
3 2017-05-04  3  1
4 2018-10-18  4  1
5 2018-10-03  5  1
qybjjes1

qybjjes13#

如果sprintf是short,则会在前面加上一个0,然后我们将其转换为Date。

as.Date(sprintf("%08d", as.numeric(date)), "%d%m%Y")
## [1] "2016-10-18" "2017-10-11" "2017-05-04" "2018-10-18" "2018-10-03"

请注意,它是矢量化的,并且在mutate内工作:

library(dplyr)
data.frame(date) %>%
    mutate(date = as.Date(sprintf("%08d", as.numeric(date)), "%d%m%Y"))
##         date
## 1 2016-10-18
## 2 2017-10-11
## 3 2017-05-04
## 4 2018-10-18
## 5 2018-10-03
hs1ihplo

hs1ihplo4#

使用sapply代替lapply。但同时,只需使用矢量化的ifelse,如下所示:

fix_date_all<- function(d){
    d <- ifelse(nchar(d) != 8, paste0("0", d), d)
    as.Date(d, "%d%m%Y")
}

df %>% 
    mutate(date = fix_date_all(date))

        date x1 x2
1 2016-10-18  1  1
2 2017-10-11  2  1
3 2017-05-04  3  1
4 2018-10-18  4  1
5 2018-10-03  5  1
>

相关问题