【问题标题】:Var in R calls function that returns a date, class says "character"R中的Var调用返回日期的函数,类说“字符”
【发布时间】:2025-12-15 12:05:04
【问题描述】:

使用 RStudio 1.1.4,可以从源代码运行,但现在进行交互测试。尝试获取 readline 输入并按日期对我的数据框进行子集化。所以这里是框架的数据结构:

'data.frame':   101242 obs. of  10 variables:
$ name      : chr (names)
$ Task_Date : Date, format: "1997-05-09" "1997-05-20" "1997-05-23" "1997-05-28" ...
$ Wo_Num    : chr  "-0-0                             " "-0-0                             " "-0-0                             " "-0-0                             " ...
$ Time_Code : chr  "SH" "SH" "SH" "SH" ...
$ Task_Code : chr  "IND-SH" "IND-SH" "IND-SH" "IND-SH" ...
$ Task      : chr  "SHOP/BREAK TIME" "SHOP/BREAK TIME" "SHOP/BREAK TIME" "SHOP/BREAK TIME" ...
$ hours     : num  2 2 1 1 2 2 2 4 5 8 ...
$ labor_rate: num  0 0 0 0 0 0 0 0 0 0 ...
$ cost      : num  148 148 74 74 148 148 148 296 370 592 ...
$ Shop      : chr  "Radio" "Radio" "Radio" "Radio" ...

以下是函数:

begdate <- function()
{
  n <-  readline(prompt = "Enter begin date:" )
  return(as.Date(n))
}

enddate <- function()
{
  n <-  readline(prompt = "Enter end date:" )
  return(as.Date(n))
}
bdate <- begdate()
edate <- enddate()

这是交互式输出:

bdate

输入开始日期:12/31/2017

类(日期)

[1]“字符”

(为 edate 运行它也是如此)

果然,

TLSub = bdate)

charToDate(x) 中的错误: 字符串不是标准的明确格式

我在这里缺少什么? 感谢您的帮助

【问题讨论】:

  • as.Date.date 要求输入是 date 对象。使用as.Date()
  • RStudio 版本无关 - 给 R 版本。
  • 当我运行示例代码时,由于 Alex 指出的错误,它死了,并显示以下消息:Error in as.Date.date(n) : 'n' is not a "date" object。我认为我们没有看到真正的代码。
  • 如果我使用 as.Date 而不是 as.Date.date,我会收到 Mark 的错误消息。原因是 R 永远不会猜测 M/D/Y 格式。如果你真的想使用它,你需要在as.Date 调用中提供它,或者使用更宽容的转换函数(如anytime::anydate("12/31/2017"),它是正确的)。
  • 对不起,是的,我使用 as.Date 运行它,但由于意外擦除和记错了我使用的内容而更改了它。但除此之外,它是正确的代码。

标签: r date subset readline


【解决方案1】:

问题不在于子集,而在于转换日期字符串。

首先,我们需要区分R中日期的内部(数字)表示和日期作为字符串打印时的格式。

第二,我们必须认识到,在世界各地,人们习惯于以不同的格式书写日期。 例如,2017 年的最后一天可以写成

  • 12/31/2017
  • 12/31/17
  • 31/12/2017
  • 31.12.2017
  • 31.12.17
  • 20171231
  • 2017/12/31
  • 2017-12-31

(如果我们只考虑数字格式)。格式的不同之处在于字符串中出现的日、月和年的顺序以及用于分隔条目的字符。

不幸的是,有些格式是模棱两可的,也就是说,您无法确定使用了哪种格式以及如何解释日期字符串。例如,字符串03/04/2017代表什么日期? 2017 年 4 月 3 日还是 2017 年 3 月 4 日? (如果年份只给出两位数,情况会变得更糟,例如,03/04/05。)

这就是为什么as.Date() 有一个format 参数可以用来告诉R 如何解释给定的日期字符串。

但是,某些格式被称为明确的,因为 R 知道如何在没有额外提示的情况下解释日期字符串。首先,这是ISO 8601 standard 中定义的日期格式YYYY-MM-DD。打印日期时默认使用此格式,例如,

Sys.Date()
[1] "2018-07-04"

在输入时,as.Date() 也接受 YYYY/MM/DD,例如,

as.Date("2017/12/31")
[1] "2017-12-31"

因此,您可以通过指定format 参数来修改您的两个函数以接受您首选格式的日期字符串:

begdate <- function()
{
  n <-  readline(prompt = "Enter begin date:" )
  return(as.Date(n, format = "%m/%d/%Y"))
}

bdate <- begdate(); bdate

现在可以按照您的首选格式正常工作

Enter begin date:12/31/2017
[1] "2017-12-31"

但如果日期字符串与指定格式不匹配,将返回NA

bdate <- begdate(); bdate
Enter begin date:2017-12-31
[1] NA

随着 R 版本 3.5.0(在 CRAN 上于 2018 年 4 月 23 日发布),as.Date() 获得了一个新参数 tryFormats 如果未指定 format,则采用 format 字符串的字符向量进行尝试。

begdate <- function()
{
  n <-  readline(prompt = "Enter begin date:" )
  return(as.Date(n, tryFormats = c("%Y-%m-%d", "%Y/%m/%d", "%m/%d/%Y")))
}

现在将正确接受和解释三种不同的格式:

Enter begin date:2017-12-31
[1] "2017-12-31"
Enter begin date:12/31/2017
[1] "2017-12-31"
Enter begin date:2017/12/31
[1] "2017-12-31"

【讨论】:

  • 你是如何发现tryFormats这个论点的? as.Datestrptime(在“幕后”使用)的帮助系统中都没有提到它...
  • @RYoda, help("as.Date")Arguments 部分提到了tryFormats,至少对于我当前安装的 R 版本是 3.5.1。
  • 是的,现在我也可以找到它了!它一定是在 R 3.4.4(我的当前版本)之后引入的,上面写着 as.Date(x, format, ...),而 R 3.5.1 的帮助写着 as.Date(x, format, tryFormats = c("%Y-%m-%d", "%Y/%m/%d"), optional = FALSE, …)
  • @RYoda,你是对的,我仔细检查了发行说明:tryFormats 是在 R 版本 3.5.0 中引入的。我已经相应地更新了我的答案。感谢您指出!