r - 使用 cumsum 的输出差异

标签 r lubridate cumsum

为什么这两个操作不同?

library(lubridate)
library(magrittr)

> seconds_to_period(1:1000) %>% cumsum %>% sum
[1] 14492440
> 1:1000 %>% cumsum %>% sum
[1] 167167000

但是,我已经看到问题在于 cumsum 仅添加时间段的秒数并忽略其余部分 :
seconds_to_period(60) +  seconds_to_period(60)
[1] "2M 0S"


> cumsum(c(seconds_to_period(60), seconds_to_period(60)))
[1] 0 0

为什么这种行为是默认形式?我认为这是相当不直观的。此外,有什么方法可以克服这个问题并获得与 cumsum(1:1000) 相同的结果?使用“Period”类 lubridate 不涉及执行以下操作:
c(seconds_to_period(60), seconds_to_period(60)) %>% as.numeric %>% cumsum

最佳答案

cumsum一个原语,你可以在这里看到 https://github.com/Microsoft/microsoft-r-open/blob/master/source/src/main/cum.c什么R它是在幕后做的。此外,如果您从第 215 行阅读:

PROTECT(t = coerceVector(CAR(args), REALSXP));
    n = XLENGTH(t);
    PROTECT(s = allocVector(REALSXP, n));
    setAttrib(s, R_NamesSymbol, getAttrib(t, R_NamesSymbol));
    UNPROTECT(2); 

这是来自 period 的强制执行至 numeric并且由于周期的结构,它只保留.Data
相比
seconds_to_period(60)@.Data
seconds_to_period(59)@.Data

因此,在C级,R不做as.numeric但是更快,更有效(但您可能会说不那么微妙,因为它没有像 .Data 那样实现 as.numeric 中的其他元素)数据强制。

看起来像这样:
 setClass("Foo", representation(.Data="numeric", number1 = "numeric", number2 = "numeric"))

 bar <- new("Foo",.Data=5, number1 = 12, number2 = 31)

 cumsum(bar) 

结果是5,因为它只是强制到numeric Data
而且:
 setClass("Foo2", representation(.Data="numeric", number1 = "numeric", number2 = "numeric"))

 bar2 <- new("Foo2", number1 = 12, number2 = 31)

 cumsum(bar2) 

还给你 numeric(0)因为没有 .Data

 setClass("Foo3", representation( number1 = "numeric", number2 = "numeric"))

 bar3 <- new("Foo3", number1 = 12, number2 = 31)

 cumsum(bar3) 

这根本不起作用:没有 .Data , 在内部,R 不知道如何将其强制为 numeric当做cumsum
所以:是因为如何R在内部处理复杂的 S4 对象。
您可以随时告诉 lubridate人们创建一个新参数seconds并存储在 .Data整个 S4 对象的累计秒数。我猜这样cumsum将工作。但是现在,他们正在使用 .Data存储第二个参数。见 edit(seconds_to_period) :
function (x) 
{
  span <- as.double(x)
  remainder <- abs(span)
  newper <- period(second = rep(0, length(x)))
  slot(newper, "day") <- remainder%/%(3600 * 24)
  remainder <- remainder%%(3600 * 24)
  slot(newper, "hour") <- remainder%/%(3600)
  remainder <- remainder%%(3600)
  slot(newper, "minute") <- remainder%/%(60)
  slot(newper, ".Data") <- remainder%%(60)
  newper * sign(span)
}

最后,仅供娱乐。这是我如何制作的模拟版本 cumsum在这里工作:
setClass("Period2",representation(.Data="numeric", period="Period"))


seconds_to_period_2 <- function(x){
   (lapply(x, function(y) new("Period2", .Data=y, period=seconds_to_period(y))))
}

a<-seconds_to_period_2(1:60)

cumsum(a)

最好的事物!

关于r - 使用 cumsum 的输出差异,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55315211/

相关文章:

python - Pandas 中的动态累积求和

r - 按条件累计总和分组

r - 如何在 RStudio 中以 Debug模式运行 for 循环?

regex - 抓取带有特殊字符和大写字母的列

r - 从类似 : "%B %d, %Y" to a format: "%Y-%m-%d" in R 的格式解析日期

r - 我可以通过 ID 列和最近的日期值在 R 中连接 2 个数据帧吗

python - 如何计算从右边开始具有零值的连续列数,直到出现第一个非零元素

r - 尝试渲染站点时 pandoc 错误

r - R 中的函数返回网络中的祖先和子代

r - 将yearmon列转换为R中的月份的最后日期