R传递函数进行累加 [英] R pass function to accumulate

查看:9
本文介绍了R传递函数进行累加的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用这个累加示例来更改数据FARME中某个变量的固定增长。原例:https://community.rstudio.com/t/row-wise-iteration-in-a-dataframe-where-each-row-depends-on-previous-values/38725/2

library(dplyr)
library(purrr)

x <- tibble(a = c(1:10),
            b = c(seq(100, 140, 10), rep(NA_real_, 5)) )

x$growth = runif(10, 0.001, 0.09)

fill_in <- function(prev, new, growth = 0.03) {
  if_else(!is.na(new), new, prev * (1 + growth))
}

x <- x %>%
  mutate(b = accumulate(b, fill_in))

这是可行的,但我不能用x$Growth替换0.03。有帮助吗?

推荐答案

由于accumulate(和accumulate2)的结构,我们不能只迭代b,我们需要为每个点包括类似c(b, growth)的内容。为此,我们不会传递b,而是传递一个list向量,它可以用:

生成
with(x, pmap(list(b, growth), c))
# [[1]]
# [1] 100.0000000   0.0265944
# [[2]]
# [1] 110.00000000   0.07115916
# [[3]]
# [1] 120.00000000   0.03739895
# [[4]]
# [1] 130.00000000   0.07958855
# [[5]]
# [1] 140.00000000   0.08470159
# [[6]]
# [1]          NA 0.005054528
# [[7]]
# [1]         NA 0.04800139
# [[8]]
# [1]         NA 0.08042529
# [[9]]
# [1]         NA 0.05007772
# [[10]]
# [1]         NA 0.04163871

有了这个,我们现在可以累计:

fill_in2 <- function(prev, new) if (is.na(new[1])) prev[1]*(1+new[2]) else new[1]
options(pillar.sigfig = 5)
x %>%
  mutate(b = accumulate(pmap(list(b, growth), c)[-1], .init = b[1], fill_in2))
# # A tibble: 10 x 3
#        a      b    growth
#    <int>  <dbl>     <dbl>
#  1     1 100    0.026594 
#  2     2 110    0.071159 
#  3     3 120    0.037399 
#  4     4 130    0.079589 
#  5     5 140    0.084702 
#  6     6 140.71 0.0050545
#  7     7 147.46 0.048001 
#  8     8 159.32 0.080425 
#  9     9 167.30 0.050078 
# 10    10 174.27 0.041639 

我同时执行pmap(..)[-1].init=b[1]的原因是,使用accumulate的默认行为,.x的第一个元素是按原样传递的;在这种情况下,这将作为第一个返回值传递c(100, 0.0266),这不是我们想要的。为解决此问题,我们将其从pmap列表中删除,并将b[1]添加为accumulate的初始化值(.init=)。

btw:这是使用growth当前值应用于b上一个值。

另一个BTW:您使用的fill_in已使用if_else。虽然它有效,但它是不必要的,也是不合适的。如果要查找长度始终为1的if对象,则使用if(也可以使用else);如果要查找向量的条件,则使用ifelse/if_else。虽然当您知道if_else的长度始终为1时,可以使用if_else,但开销和可能发生的其他事情是完全不必要的(在基本R中,ifelse会对非平凡的类数据产生后果和副作用,因此应该对其使用进行管理)。

由于accumulate一次只使用一行数据调用函数,因此使用if更合适。


数据

set.seed(123)
x <- tibble(a = c(1:10),
            b = c(seq(100, 140, 10), rep(NA_real_, 5)),
            growth = runif(10, 0.001, 0.09))

这篇关于R传递函数进行累加的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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