将倒数第二个值为.init的累加函数用作.init参数 [英] Using accumulate function with second to last value as .init argument

查看:6
本文介绍了将倒数第二个值为.init的累加函数用作.init参数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近遇到了一个有趣的问题,如何使用倒数第二个值作为.init参数加上另一个向量的当前值来计算向量值。以下是示例数据集:

set.seed(13)
dt <- data.frame(id = rep(letters[1:2], each = 5), time = rep(1:5, 2), ret = rnorm(10)/100)
dt$ind <- if_else(dt$time == 1, 120, if_else(dt$time == 2, 125, as.numeric(NA)))

   id time          ret ind
1   a    1  0.005543269 120
2   a    2 -0.002802719 125
3   a    3  0.017751634  NA
4   a    4  0.001873201  NA
5   a    5  0.011425261  NA
6   b    1  0.004155261 120
7   b    2  0.012295066 125
8   b    3  0.002366797  NA
9   b    4 -0.003653828  NA
10  b    5  0.011051443  NA

我想计算的是:

ind_{t}=ind_{t-2}*(1+ret_{t})

我尝试了以下代码。由于.init在这里没有用处,我尝试将原始.init作废,并创建了一个虚拟.init,但遗憾的是它不会将新创建的值(从第三行向下)拖入计算:

dt %>%
  group_by(id) %>%
  mutate(ind = c(120, accumulate(3:n(), .init = 125, 
                                 ~ .x * 1/.x * ind[.y - 2] * (1 + ret[.y]))))

# A tibble: 10 x 4
# Groups:   id [2]
   id     time      ret   ind
   <chr> <int>    <dbl> <dbl>
 1 a         1  0.00554  120 
 2 a         2 -0.00280  125 
 3 a         3  0.0178   122.
 4 a         4  0.00187  125.
 5 a         5  0.0114    NA 
 6 b         1  0.00416  120 
 7 b         2  0.0123   125 
 8 b         3  0.00237  120.
 9 b         4 -0.00365  125.
10 b         5  0.0111    NA 

我想知道是否可以对这段代码做一些调整,使其完全工作。 如蒙提前给予帮助,我将不胜感激

推荐答案

使用由Ind的当前值和Ind的先前值组成的状态向量。这样,先前状态包含IND的第二先前值。我们将其编码为复数值,其中实部等于Ind,虚部等于Ind的先前值。最后,我们扮演真正的角色。

library(dplyr)
library(purrr)

dt %>%
  group_by(id) %>%
  mutate(result = c(ind[1],
                    Re(accumulate(.x = tail(ret, -2), 
                                  .f = ~ Im(.x) * (1 + .y) + Re(.x) * 1i,
                                  .init = ind[2] + ind[1] * 1i)))) %>%
  ungroup

给予:

# A tibble: 10 x 5
   id     time      ret   ind result
   <chr> <int>    <dbl> <dbl>  <dbl>
 1 a         1  0.00554   120   120 
 2 a         2 -0.00280   125   125 
 3 a         3  0.0178     NA   122.
 4 a         4  0.00187    NA   125.
 5 a         5  0.0114     NA   124.
 6 b         1  0.00416   120   120 
 7 b         2  0.0123    125   125 
 8 b         3  0.00237    NA   120.
 9 b         4 -0.00365    NA   125.
10 b         5  0.0111     NA   122.

变体

这个变化去掉了复数,用2个元素的向量来代替每个复数,第一个数对应于前一个解中的实数部分,每对的第二个数对应于虚数部分。这可以扩展到每个州需要超过2个数字并且依赖关系涉及所有最后N个值的情况,但对于这里的问题,从数字对列表中提取结果的额外代码行的缺点是比在前一个解决方案中使用Re更复杂。

dt %>%
  group_by(id) %>%
  mutate(result = c(ind[1],
                    accumulate(.x = tail(ret, -2), 
                               .f = ~ c(.x[2] * (1 + .y), .x[1]),
                               .init = ind[2:1])),
         result = map_dbl(result, first)) %>%
  ungroup

选中

我们检查以上结果是否正确。或者,这也可以用作直接的解决方案。

calc <- function(ind, ret) {
  for(i in seq(3, length(ret))) ind[i] <- ind[i-2] * (1 + ret[i])
  ind
}

dt %>%
  group_by(id) %>%
  mutate(result = calc(ind, ret)) %>%
  ungroup

给予:

# A tibble: 10 x 5
   id     time      ret   ind result
   <chr> <int>    <dbl> <dbl>  <dbl>
 1 a         1  0.00554   120   120 
 2 a         2 -0.00280   125   125 
 3 a         3  0.0178     NA   122.
 4 a         4  0.00187    NA   125.
 5 a         5  0.0114     NA   124.
 6 b         1  0.00416   120   120 
 7 b         2  0.0123    125   125 
 8 b         3  0.00237    NA   120.
 9 b         4 -0.00365    NA   125.
10 b         5  0.0111     NA   122.

这篇关于将倒数第二个值为.init的累加函数用作.init参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆