使用 cumsum 的输出差异
Difference in outputs using 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 在执行 cumsum
时不知道如何将其强制为 numeric
所以:这是因为 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)
最好!
为什么这两个操作不同?
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 在执行 cumsum
numeric
所以:这是因为 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)
最好!