代码之家  ›  专栏  ›  技术社区  ›  DTYK

使用apply函数将选定列从POSIXct转换为具有特定格式的日期

  •  1
  • DTYK  · 技术社区  · 8 年前

    有时,我会将Microsoft Excel中的数据读入R。在Excel中,日期变量的格式正确(例如,2017年12月31日)。读入R后,同一日期变量转换为另一格式(例如2017-12-31)。

    我的数据帧的示例(在读入R之后)如下所示:

    df <- structure(list(ID = c("001", "002", "003", "004", "005"), 
               t1_date = structure(c(1490227200, 1508198400, 1511395200, 1527292800, 1485216000), 
                                             class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
               t2_date = structure(c(1524009600, NA, NA, NA, 1523232000), 
                                             class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
               t3_date = c(NA, NA, NA, NA, NA), 
               t4_date = c(NA, NA, NA, NA, NA), 
               t5_date = c(NA, NA, NA, NA, NA)), 
          .Names = c("ID", "t1_date", "t2_date", "t3_date", "t4_date", "t5_date"), 
          row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"))
    

    以t1_日期变量为例,我可以将POSIXct类(R为我选择)中的每个日期列单独转换为日期类,然后使用以下代码更改格式:

    df$t1_date <- as.Date(df$t1_date)
    df$t1_date <- format(df$t1_date, "%d-%b-%Y")
    

    但是,我有许多日期列,它们在数据帧中可能彼此不相邻。

    通常,为了解决这些问题,我使用 which 和 apply 函数选择相关列并对其应用函数:

    df[, which(colnames(df) == "t1_date"):
     which(colnames(df) == "t5_date")] <- 
      apply(df[, which(colnames(df) == "t1_date"):
             which(colnames(df) == "t5_date")], 2, function(x) as.Date(x, format = "%d-%b-%Y"))
    

    上面的代码导致了所有日期列中的NAs,我不确定原因。即使我不强制更改格式,但将日期列从POSIXct类转换为日期类,代码仍然无法工作(请参见下文):

    df[, which(colnames(df) == "t1_date"):
     which(colnames(df) == "t5_date")] <- 
      apply(df[, which(colnames(df) == "t1_date"):
             which(colnames(df) == "t5_date")], 2, as.Date)
    

    我想要的结果是将日期转换为DD-MMM-YYYY格式(例如,2017年12月31日)。

    感谢帮助。谢谢!

    1 回复  |  直到 8 年前
        1
  •  1
  •   Ronak Shah    8 年前

    我们选择要格式化的列的范围,然后使用 as.Date 然后 format 根据我们的要求。

    start_col <- which(colnames(df) == "t1_date")
    end_col <-  which(colnames(df) == "t5_date")
    df[start_col:end_col] <- lapply(df[start_col:end_col], 
                            function(x) format(as.Date(x), "%d-%b-%Y"))
    
    
    df
    # A tibble: 5 x 6
    #  ID    t1_date     t2_date     t3_date t4_date t5_date
    #  <chr> <chr>       <chr>       <chr>   <chr>   <chr>  
    #1 001   23-Mar-2017 18-Apr-2018 NA      NA      NA     
    #2 002   17-Oct-2017 NA          NA      NA      NA     
    #3 003   23-Nov-2017 NA          NA      NA      NA     
    #4 004   26-May-2018 NA          NA      NA      NA     
    #5 005   24-Jan-2017 09-Apr-2018 NA      NA      NA    
    

    同样可以通过 dplyr , mutate_at

    library(dplyr)
    df %>%
      mutate_at(vars("t1_date":"t5_date"), funs(format(as.Date(.), "%d-%b-%Y")))
    
    
    #  ID    t1_date     t2_date     t3_date t4_date t5_date
    #  <chr> <chr>       <chr>       <chr>   <chr>   <chr>  
    #1 001   23-Mar-2017 18-Apr-2018 NA      NA      NA     
    #2 002   17-Oct-2017 NA          NA      NA      NA     
    #3 003   23-Nov-2017 NA          NA      NA      NA     
    #4 004   26-May-2018 NA          NA      NA      NA     
    #5 005   24-Jan-2017 09-Apr-2018 NA      NA      NA