嗨,我想在R中做一些看起来应该很简单的事情,但是我似乎正在脑力衰退。
对于data.frame中的每一行,我想获取上一行中的Vol
的值,为此行添加In
的值,并减去一个依赖于该值的值。
这是我的尝试,但是滞后只是在开始时向后看一排值,一旦计算出下一个值,就不会继续往后看
library(dplyr)
df <- data.frame(In = c(1,4,0,0,1,2,3,0,0), Vol = c(1,rep(NA,8)))
df %>% mutate(Vol = (lag(Vol) + In) - (lag(Vol) + In)*0.01)
所需的输出=
In Vol
1 1 1.00
2 4 4.95
3 0 4.90
4 0 4.85
5 1 5.79
6 2 7.72
7 3 10.61
8 0 10.50
9 0 10.40
答案 0 :(得分:5)
这是使用accumulate
软件包中的purrr
的解决方案。 accumulate
函数可以将具有两个参数(例如x
和y
)的函数应用于向量序列。返回值将成为下一轮的输入值。
在下面的示例中,我要求accumulate
函数从In
列的第二个数字开始到结尾。我还为1
参数提供了.init
,它将成为函数的第一个x
。
library(dplyr)
library(purrr)
df <- data.frame(In = c(1,4,0,0,1,2,3,0,0), Vol = c(1,rep(NA,8)))
df %>%
mutate(Vol = accumulate(In[2:n()], function(x, y) (x + y) * 0.99, .init = 1))
# In Vol
# 1 1 1.000000
# 2 4 4.950000
# 3 0 4.900500
# 4 0 4.851495
# 5 1 5.792980
# 6 2 7.715050
# 7 3 10.607900
# 8 0 10.501821
# 9 0 10.396803
此外,似乎Vol
列中的第一个值与In
列中的第一个值相同。如果您只想在accumulate
列上进行In
处理,则下面的代码将更加简洁,甚至不需要将第一个值复制到{{1} }列。
Vol
答案 1 :(得分:2)
从上一行获取值并更新当前行中的值似乎是一项艰巨的任务。但是,mutate
没有计算出的先前Vol
值的“知识”,因为它会一起计算整个列的值。
在这种情况下,我们可以使用简单的for
循环
for (i in 2:nrow(df)) {
df$Vol[i] = (df$Vol[i-1] + df$In[i]) - (df$Vol[i-1] + df$In[i])*0.01
}
df
# In Vol
#1 1 1.000000
#2 4 4.950000
#3 0 4.900500
#4 0 4.851495
#5 1 5.792980
#6 2 7.715050
#7 3 10.607900
#8 0 10.501821
#9 0 10.396803
数据
test = c(1, 4, 0, 0, 1, 2, 3, 0, 0)
df <- data.frame(In = test, Vol = c(1,rep(NA,8)))
答案 2 :(得分:2)
在这种情况下,您可以使用代数运算来表示所有Vol
的第一个Vol
transform(df, Vol = c(df$Vol[1], sapply(2:NROW(df), function(n){
0.99^(n-1) * df$Vol[1] + sum(0.99^((n-1):1) * df$In[2:n])
})))
# In Vol
#1 1 1.000000
#2 4 4.950000
#3 0 4.900500
#4 0 4.851495
#5 1 5.792980
#6 2 7.715050
#7 3 10.607900
#8 0 10.501821
#9 0 10.396803
答案 3 :(得分:2)
带有Reduce
transform(df,
Vol = Reduce(function(x, y){
x + y - 0.01 * (x + y)
},
c(df$Vol[1], df$In[-1]),
accumulate = TRUE))
# In Vol
#1 1 1.000000
#2 4 4.950000
#3 0 4.900500
#4 0 4.851495
#5 1 5.792980
#6 2 7.715050
#7 3 10.607900
#8 0 10.501821
#9 0 10.396803
答案 4 :(得分:2)
您还可以使用sapply
基上的R
来替换@Ronak的for
循环。 invisible
不是必需的功能,只是包裹在sapply
周围即可使其安静地工作。
invisible(
sapply(2:nrow(df), function(i) {
df$Vol[i] <<- (df$Vol[i-1] + df$In[i]) - (df$Vol[i-1] + df$In[i])*0.01
}
)
)
> df
In Vol
1 1 1.000000
2 4 4.950000
3 0 4.900500
4 0 4.851495
5 1 5.792980
6 2 7.715050
7 3 10.607900
8 0 10.501821
9 0 10.396803
微基准测试:
Unit: microseconds
expr min lq mean median uq max neval
tidy1 578.614 602.3825 736.8518 647.7345 792.1560 3409.963 100
tidy2 566.256 601.1450 1524.3789 646.5240 801.3490 80219.732 100
for.loop 4936.829 5288.2650 6007.9584 5635.4895 6540.4290 8982.346 100
sapply 198.919 218.8710 305.8182 226.3600 243.1750 4489.870 100
trans.db.reduce 127.456 149.8150 175.4649 172.6280 195.9935 292.835 100
trans.db 217.416 236.1150 328.3348 255.2275 285.5560 5805.963 100