【问题标题】:How to convert variable with mixed date formats to one format?如何将具有混合日期格式的变量转换为一种格式?
【发布时间】:2014-10-17 06:46:15
【问题描述】:

我的数据框示例:

                date
1   25 February 1987
2     20 August 1974
3     9 October 1984
4     18 August 1992
5  19 September 1995
6          16-Oct-63
7          30-Sep-65
8        22 Jan 2008
9         13-11-1961
10    18 August 1987
11         15-Sep-70
12    5 October 1994
13   5 December 1984
14          03/23/87
15    30 August 1988
16        26-10-1993
17    22 August 1989
18         13-Sep-97

我有一个带有多种日期格式的日期变量的大型数据框。变量中的大多数格式如上所示 - 还有一些非常罕见的其他格式。之所以有多种格式,是因为数据是从各个使用不同格式的网站中提取的。

我尝试过使用简单的转换,例如

strftime(mydf$date,"%d/%m/%Y")

但如果有多种格式,这些类型的转换将不起作用。我不想诉诸多种 gsub 类型的编辑。我想知道我是否缺少更简单的解决方案?

代码示例:

    structure(list(date = structure(c(12L, 8L, 18L, 6L, 7L, 4L, 14L, 
10L, 1L, 5L, 3L, 17L, 16L, 11L, 15L, 13L, 9L, 2L), .Label = c("13-11-1961", 
"13-Sep-97", "15-Sep-70", "16-Oct-63", "18 August 1987", "18 August 1992", 
"19 September 1995", "20 August 1974", "22 August 1989", "22 Jan 2008", 
"03/23/87", "25 February 1987", "26-10-1993", "30-Sep-65", "30 August 1988", 
"5 December 1984", "5 October 1994", "9 October 1984"), class = "factor")), .Names = "date", row.names = c(NA, 
-18L), class = "data.frame")

【问题讨论】:

    标签: r date formatting


    【解决方案1】:

    您可以尝试使用orders 参数包lubridate 中的parse_date_time,它“允许用户指定多个格式顺序来处理异构日期时间字符表示”。比如……

    library(lubridate)
    parse_date_time(x = df$date,
                    orders = c("d m y", "d B Y", "m/d/y"),
                    locale = "eng")
    

    ...应该能够处理您的大多数格式。请注意b/B formats are locale sensitive

    orders 中可以使用的其他日期时间格式列在?strptime详细信息部分。

    【讨论】:

    • 这是一个非常棒的功能。
    • @Henrik - 我还不能让它工作,我认为是因为我的变量中有其他格式。例如我应该如何在订单参数格式中包含“1975 年 8 月 31 日星期三”或“2003 年 1 月 12 日星期日” - ?我认为这将是“A d m y”和“a d m y” - 对吗?
    • @Henrik - 它实际上现在似乎工作得很好。我仍然想知道是否需要考虑日期名称,但它似乎也能很好地处理这些格式。
    • @jalapic,从?parse_date_time 看来,您可以使用aA。但是,a d m y对我不起作用。不过,完全跳过工作日是有效的:parse_date_time(c("Wednesday 31 August 1975", "Sun 12 Jan 2003"), orders = c("d b y"), locale = "eng")。奇怪你不需要a/A...
    • @jalapic,仅供参考,我在lubridate github 上的order 中发布了指定工作日(a/A)的问题。
    【解决方案2】:

    这是一个基本解决方案:

    fmts <- c("%d-%b-%y", "%d %b %Y", "%d-%m-%Y", "%m/%d/%y")
    d <- as.Date(as.numeric(apply(outer(DF$date, fmts, as.Date), 1, na.omit)), "1970-01-01")
    

    我们做了一个简化的假设,即每个输入日期只有一种格式有效。示例中似乎就是这种情况,但如果没有将na.omit 替换为function(x) c(na.omit(x), NA)[1])

    请注意,两位数的年份可能不明确,但这里似乎应该总是过去,所以如果不是,我们减去 100 年:

     past <- function(x) ifelse(x > Sys.Date(), seq(from=x, length=2, by="-100 year")[2], x)
     as.Date(sapply(d, past), "1970-01-01")
    

    最后一行给出的示例数据:

    [1] "1987-02-25" "1974-08-20" "1984-10-09" "1992-08-18" "1995-09-19"
    [6] "1963-10-16" "1965-09-30" "2008-01-22" "1961-11-13" "1987-08-18"
    [11] "1970-09-15" "1994-10-05" "1984-12-05" "1987-03-23" "1988-08-30"
    [16] "1993-10-26" "1989-08-22" "1997-09-13"
    

    【讨论】:

      【解决方案3】:

      尝试编写一个函数,然后再调用它。例如: 您有一个字符串“dd-mm-yyyy”,并且只想从中提取月份,然后

      month <- function(date_var){
        # Store the month value in month
        ay_month<- as.Date(date_var,format = "%d-%m-%Y")
        month <- format(date_var, "%m")
        return(month)
      }
      

      现在通过在向量中查找月份,将字符格式更改为日期。输出将是 04

      month(as.Date("12-04-2014", format = "%d-%m-%Y"))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-06-09
        • 2017-08-27
        相关资源
        最近更新 更多