【问题标题】:why does split coerce double to integer in R and is there a workaround为什么在 R 中将强制拆分为整数倍,是否有解决方法
【发布时间】:2015-03-08 09:31:19
【问题描述】:

可以在 R 中从数字类型甚至小数值构建日期。这不是很常见,但例如在平均日期时会发生这种情况。不幸的是,他们似乎打破了split

> as.Date(-1, origin = "1970-01-01")
[1] "1969-12-31"
> as.Date(-1.0001, origin = "1970-01-01")
[1] "1969-12-30"
> split(as.Date(-1, origin = "1970-01-01"), 1)[[1]]
[1] "1969-12-31"
> split(as.Date(-1.0001, origin = "1970-01-01"), 1)[[1]]
[1] "1969-12-31" #this is wrong
> unclass(split(as.Date(-1, origin = "1970-01-01"), 1)[[1]])
[1] -1
> unclass(split(as.Date(-1.0001, origin = "1970-01-01"), 1)[[1]])
[1] -1 #this is "why"

因此,split 使两个不同的日期相等。人们同意这是一个错误还是我错过了深层原因?任何解决方法?谢谢

【问题讨论】:

  • 稻草人解决方法:lapply(split(as.character(dates), index), as.Date)。保留日期但更改基础表示。需要lapply,在某些情况下很慢。

标签: r split type-conversion


【解决方案1】:

无论出于何种原因,split.DateDate 输入强制转换为整数:

> split.Date
function (x, f, drop = FALSE, ...) 
{
    y <- split.default(as.integer(x), f, drop = drop)
    for (i in seq_along(y)) class(y[[i]]) <- "Date"
    y
}
<bytecode: 0x2effb98>
<environment: namespace:base>

这至少是函数和文档之间的不合适之处,因为?Date 说,“日期应该是一个整数,但这在内部表示中没有强制执行。”。有些人可能认为这是一个错误。我不确定。

您可以通过直接调用split.default 来避免这种情况。

> split.default(as.Date(-1.0001, origin = "1970-01-01"), 1)[[1]]
[1] "1969-12-30"

【讨论】:

  • 不可能!!似乎编写此方法的唯一目标是引入此错误。默认工作正常。谢谢
  • @piccolbo svn annotate src/library/base/R/dates.R 引导我到stat.ethz.ch/pipermail/r-devel/2008-July/050134.html,引入的动机是性能(对于>1e6 个元素的向量仍然很重要)。虽然显然正确更重要。
  • 感谢@MartinMorgan,让他们免去了更多痛苦。似乎所有时间都被 split.default 花费在 for 循环分配中,最后一行之前。不知道为什么这么慢。妥协可以用 as.numeric 替换 as.integer,但这会使双日期的使用更加普遍,正如你所说,这充其量是不确定的。更好的折衷方案可能是 x = if(is.double(x)) x else as.integer(x)。鉴于我的错误报告记录,我将把它留给其他人提交。
  • @piccolbo 这将在 R 的下一个版本中修复(基本上是 unclass() 而不是 as.integer())
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 2015-03-14
  • 1970-01-01
  • 2020-11-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多