为啥 Date 以“double”类型返回?

Posted

技术标签:

【中文标题】为啥 Date 以“double”类型返回?【英文标题】:Why is Date is being returned as type 'double'?为什么 Date 以“double”类型返回? 【发布时间】:2017-01-20 09:40:52 【问题描述】:

我在使用 R 中的 as.Date 函数时遇到了一些问题。我有一个日期向量,我正在从一个 .csv 文件中读取该日期向量,这些日期作为整数或字符的因子传入(取决于关于我如何读取文件,但这似乎与问题无关),格式为%m/%d/%Y

我正在逐行浏览文件,提取日期字段并尝试使用以下代码将其转换为在其他地方使用:

tmpDtm <- as.Date(as.character(tempDF$myDate), "%m/%d/%Y")

这似乎给了我想要的东西,例如,如果我对 2014 年 12 月 30 日的起始值执行此操作,我会返回值 "2014-12-30"。但是,如果我使用typeof() 检查这个值,R 会告诉我它的数据类型是“double”。此外,如果我尝试将其绑定到其他值并使用 c()cbind() 将其存储在数据框中,在数据框中,它最终会存储为 16434,这在我看来就像某种不同的内部日期的存储值。我很确定它也是如此,因为如果我尝试使用 as.Date() 再次转换该值,它会抛出一个询问来源的错误。

那么,有两个问题:这符合预期吗?如果是这样,是否有更合适的方法来转换日期,以便我最终得到一个日期类型的对象?

谢谢

【问题讨论】:

请做一个可重现的例子。您c()cbind() 它的数据类型是什么?您知道向量的所有条目都必须属于同一类型吗? 我知道这一点。我很抱歉不清楚,但在我尝试绑定之前数据类型是 double (即上面的 tmpDtm 对象是 type: double )。绑定问题对我来说不太重要 - 如果我可以确保在绑定之前有一个日期对象,我可以弄清楚如何以我需要的方式将它绑定到其他数据 - 我只是认为额外的信息可能会有所帮助在我进行绑定之前确定转换发生了什么。 我个人不知道这两个函数之间的细微差别,但是尝试class而不是typeof。前者似乎返回Date,而后者返回double 下面的答案不完整。这个问题应该迁移到 Stack Overflow。那里有很多解释。包括,为什么 c()cbind() 强制这个值?整数日期究竟代表什么? typeofclass 有什么区别?是否还有其他不受此强制的日期对象? 帮助(日期)说Dates are represented as the number of days since 1970-01-01, with negative values for earlier dates. 【参考方案1】:

日期在内部表示为双精度,如下例所示:

> typeof(as.Date("09/12/16", "%m/%d/%y"))
[1] "double"

它仍然被标记为一个类日期,如

> class(as.Date("09/12/16", "%m/%d/%y"))
[1] "Date"

因为它是一个双精度数,所以你可以用它进行计算。但是因为它属于 Date 类,所以这些计算会导致 Dates:

> as.Date("09/12/16", "%m/%d/%y") + 1
[1] "2016-09-13"
> as.Date("09/12/16", "%m/%d/%y") + 31
[1] "2016-10-13"

编辑 我要求c()cbind(),因为它们可能与一些奇怪的行为有关。请参见以下示例,其中在c 中切换顺序不会更改结果的类型而是更改结果的类:

> c(as.Date("09/12/16", "%m/%d/%y"), 1)
[1] "2016-09-12" "1970-01-02"
> c(1, as.Date("09/12/16", "%m/%d/%y"))
[1]     1 17056

> class(c(as.Date("09/12/16", "%m/%d/%y"), 1))
[1] "Date"
> class(c(1, as.Date("09/12/16", "%m/%d/%y")))
[1] "numeric"

EDIT 2 - c()cbind 强制对象为一种类型。第一次编辑显示了强制异常,但通常,向量必须是一个共享类型。 cbind 共享此行为,因为它强制转换为矩阵,而矩阵又强制转换为单一类型。

有关typeofclass 的更多帮助,请参阅this link

【讨论】:

查看methods("c")。在 S3 系统中,第一个参数的类决定了使用哪种方法。 ccbind 都是 S3 泛型。如果你想不管顺序都得到相同的结果,你需要使用 S4 类,它可以根据所有参数的签名进行方法分派。【参考方案2】:

这符合预期。你用过typeof();你可能应该使用class():

R> Sys.Date()
[1] "2016-09-12"
R> typeof(Sys.Date())       # this more or less gives you how it is stored
[1] "double"
R> class(Sys.Date())        # where as this gives you _behaviour_
[1] "Date"
R> 

小广告:我有一个新包 anytime,目前在 CRAN 收到,它处理这个问题,因为它将“任何东西”转换为 POSIXct(通过anytime())或日期(通过anydate()

例如:

R> anydate("12/30/2014")             # no format needed
[1] "2014-12-30"
R> anydate(as.factor("12/30/2014"))  # converts from factor too
[1] "2014-12-30"
R> 

【讨论】:

期待anytime 它现在在 CRAN 上 :) 看过了。看不到它记录在哪里处理起源。例如。 anydate(43930) 返回“2090-04-11”而不是“2020-04-11”,原点为 1900-01-01。 抱歉,您正在评论四年多的评论。我在anytime 中进行了更改,因为您检查了它的新闻和/或文档吗?如果您确实发现了问题,请将其报告为 GitHub 问题(最好使用可重现的示例)。谢谢! 在帮助页面的第一段中,在描述下:“...对象将日期和时间表示为自 1970 年 1 月 1 日‘纪元’以来的(可能是小数)秒。”所以anydate(0) 是 1970 年 1 月 1 日,anydate(2) 是 1 月 3 日。因此,anydate(43930) 是那个时代之后的 44k 天。

以上是关于为啥 Date 以“double”类型返回?的主要内容,如果未能解决你的问题,请参考以下文章

我在写一个java泛型接口实现时为啥报出double为意外的类型啊?源程序如下!

JSP页面显示 Date 和 Double数据类型类时自定义显示格式

c语言,double类型数值比较为啥出错,如何比较两个double类型大小?

java中"(double)(Math.round(x3 * 10000))/10000"为啥这个东西会输出小数啊?

为啥在传递 long long 时调用具有两个 double 类型参数的重载函数?

在java中的double和float类型数据相除为啥可以除以零