【问题标题】:Changing date format in R在 R 中更改日期格式
【发布时间】:2011-11-18 09:24:51
【问题描述】:

我在 R 中有一些非常简单的数据需要更改其日期格式:

 date midpoint
1   31/08/2011   0.8378
2   31/07/2011   0.8457
3   30/06/2011   0.8147
4   31/05/2011   0.7970
5   30/04/2011   0.7877
6   31/03/2011   0.7411
7   28/02/2011   0.7624
8   31/01/2011   0.7665
9   31/12/2010   0.7500
10  30/11/2010   0.7734
11  31/10/2010   0.7511
12  30/09/2010   0.7263
13  31/08/2010   0.7158
14  31/07/2010   0.7110
15  30/06/2010   0.6921
16  31/05/2010   0.7005
17  30/04/2010   0.7113
18  31/03/2010   0.7027
19  28/02/2010   0.6973
20  31/01/2010   0.7260
21  31/12/2009   0.7154
22  30/11/2009   0.7287
23  31/10/2009   0.7375

而不是%d/%m/%Y,我想要%Y-%m-%d的标准R格式

如何进行此更改?我试过了:

nzd$date <- format(as.Date(nzd$date), "%Y/%m/%d")

但这只是切断了年份并在当天添加了零:

 [1] "0031/08/20" "0031/07/20" "0030/06/20" "0031/05/20" "0030/04/20"
 [6] "0031/03/20" "0028/02/20" "0031/01/20" "0031/12/20" "0030/11/20"
 [11] "0031/10/20" "0030/09/20" "0031/08/20" "0031/07/20" "0030/06/20"
 [16] "0031/05/20" "0030/04/20" "0031/03/20" "0028/02/20" "0031/01/20"
 [21] "0031/12/20" "0030/11/20" "0031/10/20" "0030/09/20" "0031/08/20"
 [26] "0031/07/20" "0030/06/20" "0031/05/20" "0030/04/20" "0031/03/20"
 [31] "0028/02/20" "0031/01/20" "0031/12/20" "0030/11/20" "0031/10/20"
 [36] "0030/09/20" "0031/08/20" "0031/07/20" "0030/06/20" "0031/05/20"

谢谢!

【问题讨论】:

    标签: r date format strptime r-faq


    【解决方案1】:

    这里有两个步骤:

    • 解析数据。您的示例不能完全重现,是文件中的数据,还是文本或因子变量中的变量?让我们假设后者,那么如果你的data.frame被称为X,你可以这样做
     X$newdate <- strptime(as.character(X$date), "%d/%m/%Y")
    

    现在newdate 列的类型应该是Date

    • 格式化数据。那就是打电话给format()strftime()
     format(X$newdate, "%Y-%m-%d")
    

    一个更完整的例子:

    R> nzd <- data.frame(date=c("31/08/2011", "31/07/2011", "30/06/2011"), 
    +                    mid=c(0.8378,0.8457,0.8147))
    R> nzd
            date    mid
    1 31/08/2011 0.8378
    2 31/07/2011 0.8457
    3 30/06/2011 0.8147
    R> nzd$newdate <- strptime(as.character(nzd$date), "%d/%m/%Y")
    R> nzd$txtdate <- format(nzd$newdate, "%Y-%m-%d")
    R> nzd
            date    mid    newdate    txtdate
    1 31/08/2011 0.8378 2011-08-31 2011-08-31
    2 31/07/2011 0.8457 2011-07-31 2011-07-31
    3 30/06/2011 0.8147 2011-06-30 2011-06-30
    R> 
    

    第三列和第四列之间的区别在于类型:newdate 属于 Date 类,而 txtdate 属于字符。

    【讨论】:

    • 嗯,这对于菜鸟来说似乎非常复杂。我最终只是更改了 excel 中的格式并将 csv 文件读回 R。我想知道如何在 R 中轻松更改它,以防我有一个更大的文件,但这似乎并不像它那么容易应该。这对您的解决方案并不重要,我只是希望它更简单(可能是一种在不创建新列的情况下转换原始列的方法)。有没有办法先改类再格式化?
    • @Yuri - 这本质上就是 Dirk 的回答向您展示的方法,尽管他在此过程中创建了一些新专栏,因此您可以轻松地看到“幕后”正在发生的事情。我建议逐行浏览他的示例,在每行之间插入一个str(x),这样您就可以看到不同的操作。
    • @Chase 谢谢我非常感谢用于教学目的的额外专栏,它帮助我了解班级差异以及格式;所以谢谢你!很高兴知道附加列的额外步骤并不是绝对必要的。谢谢你们!
    【解决方案2】:
    nzd$date <- format(as.Date(nzd$date), "%Y/%m/%d")
    

    在上面的代码中,有两个错误。首先,当您在as.Date 中阅读nzd$date 时,您并没有提及您以什么格式输入date。因此,它会尝试使用默认设置格式来读取它。如果你看到help 文档,?as.Date 你会看到

    格式
    一个字符串。如果未指定,它将尝试“%Y-%m-%d” 然后在第一个非 NA 元素上使用 "%Y/%m/%d",并给出错误 如果两者都不起作用。否则,通过strptime处理

    第二个错误是:即使您想以%Y-%m-%d 格式阅读它,但在format 中却写了"%Y/%m/%d"

    现在,正确的做法是:

    > nzd <- data.frame(date=c("31/08/2011", "31/07/2011", "30/06/2011"), 
    +                                       mid=c(0.8378,0.8457,0.8147))
    > nzd
            date    mid
    1 31/08/2011 0.8378
    2 31/07/2011 0.8457
    3 30/06/2011 0.8147
    > nzd$date <- format(as.Date(nzd$date, format = "%d/%m/%Y"), "%Y-%m-%d")
    > head(nzd)
            date    mid
    1 2011-08-31 0.8378
    2 2011-07-31 0.8457
    3 2011-06-30 0.8147
    

    【讨论】:

      【解决方案3】:

      您还可以使用 lubridate 包中的 parse_date_time 函数:

      library(lubridate)
      day<-"31/08/2011"
      as.Date(parse_date_time(day,"dmy"))
      [1] "2011-08-31"
      

      parse_date_time 返回一个 POSIXct 对象,所以我们使用as.Date 来获取一个日期对象。 parse_date_time 的第一个参数指定日期向量,第二个参数指定格式出现的顺序。 orders 参数使parse_date_time 非常灵活。

      【讨论】:

        【解决方案4】:

        通过textConnection 读取您的数据后,以下操作似乎有效:

        dat <- read.table(textConnection(txt), header = TRUE)
        dat$date <- strptime(dat$date, format= "%d/%m/%Y")
        format(dat$date, format="%Y-%m-%d")
        
        > format(dat$date, format="%Y-%m-%d")
         [1] "2011-08-31" "2011-07-31" "2011-06-30" "2011-05-31" "2011-04-30" "2011-03-31"
         [7] "2011-02-28" "2011-01-31" "2010-12-31" "2010-11-30" "2010-10-31" "2010-09-30"
        [13] "2010-08-31" "2010-07-31" "2010-06-30" "2010-05-31" "2010-04-30" "2010-03-31"
        [19] "2010-02-28" "2010-01-31" "2009-12-31" "2009-11-30" "2009-10-31"
        
        > str(dat)
        'data.frame':   23 obs. of  2 variables:
         $ date    : POSIXlt, format: "2011-08-31" "2011-07-31" "2011-06-30" ...
         $ midpoint: num  0.838 0.846 0.815 0.797 0.788 ...
        

        【讨论】:

        • 我确实对数据框中的 POSIXlt 有疑问,如下所示:stackoverflow.com/questions/3355107/… 当我尝试在 ggplot 中将日期绘制为 x 轴时,我收到此错误 - if ( length(range) == 1 || diff(range) == 0) { : 需要 TRUE/FALSE 的缺失值 -- 我如何在 POSIXct 中得到这个?
        • @Yuri - 类似as.POSIXct(otherStuffHere) 的东西可能会起作用。感谢您提供该链接,我不知道 Hadley 提出的这些问题。
        【解决方案5】:

        使用包 lubridate 真的很容易。您所要做的就是告诉 R 您的日期已经是什么格式。然后它将其转换为标准格式

        nzd$date &lt;- dmy(nzd$date)

        就是这样。

        【讨论】:

          【解决方案6】:

          使用一行将日期转换为首选格式:

          nzd$date <- format(as.Date(nzd$date, format="%d/%m/%Y"),"%Y/%m/%d")
          

          【讨论】:

            【解决方案7】:

            我相信

            nzd$date <- as.Date(nzd$date, format = "%d/%m/%Y")
            

            足够了。

            【讨论】:

            • 同意,但它依赖于 magic(默认格式),因此显示不同的步骤是有益的。
            猜你喜欢
            • 2015-03-03
            • 1970-01-01
            • 2019-01-09
            • 1970-01-01
            • 1970-01-01
            • 2021-12-18
            • 2021-12-19
            相关资源
            最近更新 更多