【问题标题】:How to change multiple Date formats in same column?如何更改同一列中的多个日期格式?
【发布时间】:2012-11-25 17:10:29
【问题描述】:

到目前为止,我得到的是一个数据框列,其中包含不同字符格式的日期。一些出现在%d.%m.%Y 模式中,一些出现在%m/%d/%Y 中:

data$initialDiagnose = as.character(data$initialDiagnose)
data$initialDiagnose[1:10]

[1] "14.01.2009" "9/22/2005"  "4/21/2010" "28.01.2010" "09.01.2009" "3/28/2005" "04.01.2005" "04.01.2005" "9/17/2010" "03.01.2010"

我希望它们以一种格式作为 Date(),但 R 当然拒绝。
所以我一开始尝试通过分隔符来改变它们:

data$initialDiagnose[grep('/', data$initialDiagnose)] = as.character.Date(data$initialDiagnose[grep('/', data$initialDiagnose)], format = '%m/%d/%Y')

类似于'.'日期。但它没有用。

如何将它们全部更改为一种格式,以便我可以使用它们?

【问题讨论】:

    标签: r date format


    【解决方案1】:
    a <- as.Date(data$initialDiagnose,format="%m/%d/%Y") # Produces NA when format is not "%m/%d/%Y"
    b <- as.Date(data$initialDiagnose,format="%d.%m.%Y") # Produces NA when format is not "%d.%m.%Y"
    a[is.na(a)] <- b[!is.na(b)] # Combine both while keeping their ranks
    data$initialDiagnose <- a # Put it back in your dataframe
    data$initialDiagnose
    [1] "2009-01-14" "2005-09-22" "2010-04-21" "2010-01-28" "2009-01-09" "2005-03-28" "2005-01-04" "2005-01-04" "2010-09-17" "2010-01-03"
    

    另外,前面的方法适用于您拥有三种(或更多)不同格式的情况:

    data$initialDiagnose
    [1] 14.01.2009 9/22/2005  12 Mar 97  4/21/2010  28.01.2010 09.01.2009 3/28/2005 
    Levels: 09.01.2009 12 Mar 97 14.01.2009 28.01.2010 3/28/2005 4/21/2010 9/22/2005
    
    multidate <- function(data, formats){
        a<-list()
        for(i in 1:length(formats)){
            a[[i]]<- as.Date(data,format=formats[i])
            a[[1]][!is.na(a[[i]])]<-a[[i]][!is.na(a[[i]])]
            }
        a[[1]]
        }
    
    data$initialDiagnose <- multidate(data$initialDiagnose, 
                                      c("%m/%d/%Y","%d.%m.%Y","%d %b %y"))
    data$initialDiagnose
    [1] "2009-01-14" "2005-09-22" "1997-03-12" "2010-04-21" "2010-01-28" "2009-01-09" "2005-03-28"
    

    【讨论】:

    • 这个函数健壮吗?据推测,作为参数的日期格式应按初始诊断中的出现频率排序。谢谢!
    • 只要不存在相互模棱两可的格式(例如 2010-02-03 可能是 %Y-%m-%d%Y-%d-%m),我认为出现的频率不是问题。
    【解决方案2】:

    我喜欢 lubridate 的易用性:

    library(lubridate) 
    
    # note added ugly formats below
    data <- data.frame(initialDiagnose = c("14.01.2009", "9/22/2005", 
            "4/21/2010", "28.01.2010", "09.01.2009", "3/28/2005", 
            "04.01.2005", "04.01.2005", "Created on 9/17/2010", "03 01 2010"))
    
    mdy <- mdy(data$initialDiagnose) 
    dmy <- dmy(data$initialDiagnose) 
    mdy[is.na(mdy)] <- dmy[is.na(mdy)] # some dates are ambiguous, here we give 
    data$initialDiagnose <- mdy        # mdy precedence over dmy
    data
    #   initialDiagnose
    #       2009-01-14
    #       2005-09-22
    #       2010-04-21
    #       2010-01-28
    #       2009-09-01
    #       2005-03-28
    #       2005-04-01
    #       2005-04-01
    #       2010-09-17
    #       2010-03-01
    

    【讨论】:

    • 我很欣赏/认为在这里明确定义偏好的价值是巨大的。
    【解决方案3】:

    自2012年MattBagg's answer以来,lubridate添加了parse_date_time功能,该功能正是针对这种情况而设计的,可以在一行中解决这个问题:

    library(lubridate) 
    
    data <- data.frame(initialDiagnose = c("14.01.2009", "9/22/2005", 
            "4/21/2010", "28.01.2010", "09.01.2009", "3/28/2005", 
            "04.01.2005", "04.01.2005", "Created on 9/17/2010", "03 01 2010"))
    
    parse_date_time(data$initialDiagnose, orders = c('mdy', 'dmy'))
    
     [1] "2009-01-14 UTC" "2005-09-22 UTC" "2010-04-21 UTC" "2010-01-28 UTC" "2009-01-09 UTC"
     [6] "2005-03-28 UTC" "2005-01-04 UTC" "2005-01-04 UTC" "2010-09-17 UTC" "2010-03-01 UTC"
    

    orders= 参数是一个字符向量,其中包含可能的日期时间解析格式,按照它们应该被测试的顺序。因此,通过给出c('mdy', 'dmy'),lubridate 将尝试将所有字符串解析为Month, Date, Year 格式。如果它不能成功地做到这一点(例如,日期14.01.2009 将不起作用,因为没有第 14 个月),它将尝试列表中的下一个,直到所有字符串都被解析,或者所有订单都用完。

    【讨论】:

      猜你喜欢
      • 2022-11-03
      • 2021-11-28
      • 1970-01-01
      • 2015-04-15
      • 2019-03-30
      相关资源
      最近更新 更多