通过更改行位置来遍历行,对计算进行迭代和求和 [英] Iterate and sum a calculation across rows by varying row position

查看:82
本文介绍了通过更改行位置来遍历行,对计算进行迭代和求和的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个简单的数据框,如下所示:

I have a simple dataframe as follows:

thedata <-  data.frame(values = c(30,20,10,40,20)
                     ,week = seq(from = 1, to = 5, by = 1))
thedata$lengths <-length(thedata$values):1-1

我希望对每一行进行以下计算:

I am looking to run the following calculation across each row:

values*0.2^lengths

...我想在其中迭代并求和每个累积长度.例如,第一行计算为:

...where I would like to iterate through and sum each cumulative length. For instance, the first row calculation would be:

sum(30*.20^1, 30*.20^2, 30*.20^3, 30*.20^4)

第三个是:

sum(10*.20^1, 10*.20^2)

...等等(最后一行将是0,因为它是时间序列中的最后一个值).到目前为止,我最成功的方法是循环/套用组合:

...and so forth (the last row would be 0, as it is the last value in the time series). The approach I've had most success with so far is a loop/sapply combo:

for (i in thedata$lengths){
  print(unlist(sapply(thedata[1], function(x) {x*0.2^i})))
}

但是将数据转换为正确的格式会有点混乱,我需要做一些不同的事情才能使迭代正常工作.

But it becomes a bit messy manipulating the data to the right format and I'll need to do something different to get the iteration working properly.

我一直在使用rollapply和stats :: filter/reduce组合,但收效甚微.

I've played around with rollapply and stats::filter/reduce combo with little success.

注意:这里有一个类似但更广泛的问题: 计算时间序列中的运行总和/衰减值

Note: have a similar but broader question here: Calculate running sum/decay value in time series

第二部分:

出于完整性考虑,我也对上面的相同问题感兴趣,但是附加条件是每次迭代都使用values列中的相应值.因此,第一行计算为:

For completeness, I am also interested in the same problem above, but with the added condition that each iteration uses the corresponding value from the values column. So the first row calculation would be:

sum(20*.20^1, 10*.20^2, 40*.20^3, 20*.20^4)

我认为这大部分可以通过以下代码解决:

I think this is mostly solved with this code:

thisfunc <- function(x) { w = 1:length(x); sum(x*.2^w)}
thedata$filtervalues2 <- rollapply(thedata$values, width=5,FUN=thisfunc, align="left", partial=TRUE)
thedata
shift <- function(x, n){
  c(x[-(seq(n))], rep(NA, n))
}
thedata$filtervalues2 <- shift(thedata$filtervalues2, 1)
thedata[is.na(thedata)] <- 0
thedata

  values week filtervalues2
1     30    1         4.752
2     20    2         3.760
3     10    3         8.800
4     40    4         4.000
5     20    5         0.000

虽然有些笨拙.我想我更喜欢这种sqldf方法:

Although a bit clunky. I think I prefer this sqldf approach:

thedata$values2 <-  thedata$values
trythis <- sqldf("select a.week, 
                 sum(case when b.week > a.week 
                 then b.values2*power(0.2,b.week-a.week) 
                 else 0 end) as calc1 
                 from thedata a, 
                 thedata b  
                 group by a.week")

推荐答案

看到@snoram的答案,我发现结合我们的两种方法,您可以在最少的行中得到结果:

Having seen @snoram's answer, I see that combining our two approaches you get the result in the fewest lines:

library(dplyr)

thedata %>%
  rowwise() %>%
  mutate(new = sum(values * 0.2^seq_len(lengths)))

##   values  week lengths    new
##    <dbl> <dbl>   <dbl>  <dbl>
## 1     30     1       4  7.488
## 2     20     2       3  4.960
## 3     10     3       2  2.400
## 4     40     4       1  8.000
## 5     20     5       0  0.000

原始答案

这就是我要做的:

func <- function(values, lengths) {
  calc = 0
  for(i in 1:lengths) {
    calc = calc + values * 0.2^i 
  }
  return(calc)  
}

library(dplyr)

thedata %>%
  rowwise() %>%
  mutate(new = func(values, lengths))

##   values  week lengths    new
##    <dbl> <dbl>   <dbl>  <dbl>
## 1     30     1       4  7.488
## 2     20     2       3  4.960
## 3     10     3       2  2.400
## 4     40     4       1  8.000
## 5     20     5       0 24.000

这篇关于通过更改行位置来遍历行,对计算进行迭代和求和的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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