【问题标题】:Convert character month name to date time object将字符月份名称转换为日期时间对象
【发布时间】:2017-02-07 07:42:57
【问题描述】:

我一定错过了一些简单的东西。

我有一个各种日期格式的 data.frame,我正在使用 lubridate,它适用于除月份名称本身之外的所有内容。我无法将月份名称转换为日期时间对象。

> head(dates)
    From         To
1       June     August
2    January   December
3 05/01/2013 10/30/2013
4       July   November
5 06/17/2013 10/14/2013
6 05/04/2013 11/23/2013

尝试将六月更改为日期时间对象:

> as_date(dates[1,1])
Error in charToDate(x) : 
  character string is not in a standard unambiguous format

> as_date("June")
Error in charToDate(x) : 
  character string is not in a standard unambiguous format
  • 实际年份和日期无关紧要。我只需要一个月。 zx8754 建议使用虚拟的日期和年份。

【问题讨论】:

  • 如果缺少年份,您是否假设 2013,而缺少日期时是 01?然后我们可以粘贴虚拟年、日,然后进行转换。
  • @zx8754 年份和日期无关紧要,所以是的,我认为虚拟的日子和年份会起作用。谢谢
  • 如果您想简单地将月份值转换为相应的数值(即“Dec” -> 12),那么您可以尝试match(dates[1, 1], month.abb)。

标签: r date lubridate


【解决方案1】:

以下是一个粗略的示例,说明如何实现这一目标。

鉴于虚拟值很好:

match(dates[1, 1], month.abb)

鉴于我们在dates[1. 1] 中有Dec,以上内容将返回您:

12

为了生成上面的返回值以及日期格式的虚拟数字,我尝试了:

tmp = paste(match(dates[1, 1], month.abb), "2013", sep="/")

这给了我们:

12/2013

最后:

result = paste("01", tmp, sep="/")

返回:

01/12/2013

我相信还有比这更灵活的方法;但这只是一个想法,我只是尝试过。

【讨论】:

  • 呵呵,你刚刚把我的功能分解成碎片,解释得很好。
  • @zx8754 谢谢;你的方法肯定比我的更灵活。 :-)
【解决方案2】:

lubridate 可以处理将月份的名称或缩写转换为月份的数字,当它与制作正确日期所需的其余信息(即日期和年份)配对时。例如:

lubridate::mdy("August/01/2013", "08/01/2013", "Aug/01/2013")
#> [1] "2013-08-01" "2013-08-01" "2013-08-01"

您可以利用它编写一个将“/01/2013”​​附加到任何月份名称的函数(为了安全起见,我也加入了缩写)。然后将其应用于所有日期列(dplyr::mutate_all 只是一种方法)。

name_to_date <- function(x) {
  lubridate::mdy(ifelse(x %in% c(month.name, month.abb), paste0(x, "/01/2013"), x))
}

dplyr::mutate_all(dates, name_to_date)
#>         From         To
#> 1 2013-06-01 2013-08-01
#> 2 2013-01-01 2013-12-01
#> 3 2013-05-01 2013-10-30
#> 4 2013-07-01 2013-11-01
#> 5 2013-06-17 2013-10-14
#> 6 2013-05-04 2013-11-23

【讨论】:

    【解决方案3】:

    使用自定义函数:

    # dummy data
    df1 <- read.table(text = "
    From         To
    1       June     August
    2    January   December
    3 05/01/2013 10/30/2013
    4       July   November
    5 06/17/2013 10/14/2013
    6 05/04/2013 11/23/2013", header = TRUE, as.is = TRUE)
    
    # custom function
    myFun <- function(x, dummyDay = "01", dummyYear = "2013"){
      require(lubridate)
    
      x <- ifelse(substr(x, 1, 3) %in% month.abb,
                  paste(match(substr(x, 1, 3), month.abb),
                        dummyDay,
                        dummyYear, sep = "/"), x)
      #return date
      mdy(x)
    }
    
    res <- data.frame(lapply(df1, myFun))
    
    res
    #         From         To
    # 1 2013-06-01 2013-08-01
    # 2 2013-01-01 2013-12-01
    # 3 2013-05-01 2013-10-30
    # 4 2013-07-01 2013-11-01
    # 5 2013-06-17 2013-10-14
    # 6 2013-05-04 2013-11-23
    

    【讨论】:

    • 不错的功能。我认为您可以只做df1[] &lt;- lapply(df1, myFun) 以避免重复数据集。我也想知道这些日期有什么意义,以及真正的六月一号和一些假的日期之间的 OP 会有什么不同。另外,如果From 拥有November 而To 拥有August,会发生什么?如果你问我,我会把这整个事情说成“不清楚”
    • @DavidArenburg OP 可以随心所欲地使用该功能,我更喜欢将原始输入保持为原始输入。
    • 不知道 keep raw input as raw 是什么意思,但我猜是的
    • @zx8754 这有点离题,但你为什么要使用 substr(x,1,3)。我不明白为什么 1 和 3 评估为 True。为什么 1 和 2 并且它评估它为 False?
    • @Chris 因为month.abb 给出了 3 个字母的月份名称,例如“Jan, Feb, Mar,..., Dec”。所以我说如果前 3 个字母匹配 month.abb 名称,然后使用匹配转换为数字。
    猜你喜欢
    • 2016-03-09
    • 2020-11-16
    • 2021-01-01
    • 2018-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2018-10-15
    相关资源
    最近更新 更多