R 基于以前的行更新数据帧行

R 基于以前的行更新数据帧行,r,R,给定以下数据帧(按时间排序的简单时间序列): 对于每个组(a或b)以及该组中的每一行(时间t),我希望将每一行更新为当前行(时间t)和上一行的缩放版本(时间t-1)(如果上一行不存在,则不更新) 棘手的部分是,一旦一行被更新,更新的版本(而不是原始版本)就应该用于更新下一行。我可以通过循环时间和分组来实现这一点。我想知道是否有更有效的方法使用lag()/dplyr/ set.seed(1) data <- data.frame(time = c(1:3, 1:4),

给定以下数据帧(按时间排序的简单时间序列):

对于每个组(a或b)以及该组中的每一行(时间t),我希望将每一行更新为当前行(时间t)和上一行的缩放版本(时间t-1)(如果上一行不存在,则不更新)

棘手的部分是,一旦一行被更新,更新的版本(而不是原始版本)就应该用于更新下一行。我可以通过循环时间和分组来实现这一点。我想知道是否有更有效的方法使用lag()/dplyr/

set.seed(1)
data <- data.frame(time = c(1:3, 1:4),
                   groups = c(rep(c("b", "a"), c(3, 4))),
                   value = rnorm(7), value1=rnorm(7))

alfa = 0.1
for (id in unique(data$groups)){
  data_tmp <- data[data$groups==id,]
  for (i in 2:nrow(data_tmp)){
    for (col in colnames(data)[-(1:2)]){
      data[data$groups==id,][i,][col] = data[data$groups==id,][i,][col] + alfa* data[data$groups==id,][i-1,][col]
    }
  }
}

以下是如何使用
dplyr

df1<-read.table(text="time groups      value     value1
1    1      b -0.6264538  0.7383247
2    2      b  0.1836433  0.5757814
3    3      b -0.8356286 -0.3053884
4    1      a  1.5952808  1.5117812
5    2      a  0.3295078  0.3898432
6    3      a -0.8204684 -0.6212406
7    4      a  0.4874291 -2.2146999",header=TRUE, stringsAsFactors=FALSE)


alfa  <- 0.1
func <-function(x){x+alfa*dplyr::lag(x,default = 0)}

library(dplyr)
df1 %>%
group_by(groups) %>%
mutate_each(funs(func(.)),-time)

   time groups      value     value1
  <int>  <chr>      <dbl>      <dbl>
1     1      b -0.6264538  0.7383247
2     2      b  0.1209979  0.6496139
3     3      b -0.8172643 -0.2478103
4     1      a  1.5952808  1.5117812
5     2      a  0.4890359  0.5410213
6     3      a -0.7875176 -0.5822563
7     4      a  0.4053823 -2.2768240

df1以下是如何使用
dplyr

df1<-read.table(text="time groups      value     value1
1    1      b -0.6264538  0.7383247
2    2      b  0.1836433  0.5757814
3    3      b -0.8356286 -0.3053884
4    1      a  1.5952808  1.5117812
5    2      a  0.3295078  0.3898432
6    3      a -0.8204684 -0.6212406
7    4      a  0.4874291 -2.2146999",header=TRUE, stringsAsFactors=FALSE)


alfa  <- 0.1
func <-function(x){x+alfa*dplyr::lag(x,default = 0)}

library(dplyr)
df1 %>%
group_by(groups) %>%
mutate_each(funs(func(.)),-time)

   time groups      value     value1
  <int>  <chr>      <dbl>      <dbl>
1     1      b -0.6264538  0.7383247
2     2      b  0.1209979  0.6496139
3     3      b -0.8172643 -0.2478103
4     1      a  1.5952808  1.5117812
5     2      a  0.4890359  0.5410213
6     3      a -0.7875176 -0.5822563
7     4      a  0.4053823 -2.2768240

df1您要求的基本上是一个指数加权的移动和。有一些软件包提供了支持该概念的功能,但我在一些东西上使用了一个快速功能:

EWS <- function(x, alfa = 0.1) sum(x * (alfa ^ (length(x):1 - 1)))
EWMS <- function(x, width, FUN, ...) {
  FUN <- match.fun(FUN)
  lenx <- length(x)
  for (i in tail(seq_along(x), n = 1-width)) {
    x[i] <- do.call(FUN, c(list(x[ max(1, i-width+1):i ]), list(...)))
  }
  x
}
假设“3”是最近的数据,“2”和“1”是过去的数据。(这很容易改变,这只是一个起点。)

运动部件也同样合理。我发现电子表格是一种直观的方式来演示应该发生的事情:

因此,根据@PLapointe的
dplyr
建议对其进行调整:

library(dplyr)
dat %>%
  group_by(groups) %>%
  mutate_each(funs(EWMS(., width=2, EWS)), -time) %>%
  ungroup()
# # A tibble: 7 × 4
#    time groups      value     value1
#   <int>  <chr>      <dbl>      <dbl>
# 1     1      b -0.6264538  0.7383247
# 2     2      b  0.1209979  0.6496139
# 3     3      b -0.8235288 -0.2404270
# 4     1      a  1.5952808  1.5117812
# 5     2      a  0.4890359  0.5410213
# 6     3      a -0.7715648 -0.5671385
# 7     4      a  0.4102726 -2.2714137
库(dplyr)
dat%>%
分组依据(组)%>%
每个变异(funs(EWMS(,宽度=2,EWS)),-时间%>%
解组()
##A tible:7×4
#时间组值值1
#                 
#1 b-0.6264538 0.7383247
#2 b 0.1209979 0.6496139
#3 b-0.8235288-0.2404270
#4 1 a 1.5952808 1.5117812
#5 2 a 0.4890359 0.5410213
#6.3 a-0.7715648-0.5671385
#7.4 a 0.4102726-2.2714137

您所要求的本质上是一个指数加权的移动和。有一些软件包提供了支持该概念的功能,但我在一些东西上使用了一个快速功能:

EWS <- function(x, alfa = 0.1) sum(x * (alfa ^ (length(x):1 - 1)))
EWMS <- function(x, width, FUN, ...) {
  FUN <- match.fun(FUN)
  lenx <- length(x)
  for (i in tail(seq_along(x), n = 1-width)) {
    x[i] <- do.call(FUN, c(list(x[ max(1, i-width+1):i ]), list(...)))
  }
  x
}
假设“3”是最近的数据,“2”和“1”是过去的数据。(这很容易改变,这只是一个起点。)

运动部件也同样合理。我发现电子表格是一种直观的方式来演示应该发生的事情:

因此,根据@PLapointe的
dplyr
建议对其进行调整:

library(dplyr)
dat %>%
  group_by(groups) %>%
  mutate_each(funs(EWMS(., width=2, EWS)), -time) %>%
  ungroup()
# # A tibble: 7 × 4
#    time groups      value     value1
#   <int>  <chr>      <dbl>      <dbl>
# 1     1      b -0.6264538  0.7383247
# 2     2      b  0.1209979  0.6496139
# 3     3      b -0.8235288 -0.2404270
# 4     1      a  1.5952808  1.5117812
# 5     2      a  0.4890359  0.5410213
# 6     3      a -0.7715648 -0.5671385
# 7     4      a  0.4102726 -2.2714137
库(dplyr)
dat%>%
分组依据(组)%>%
每个变异(funs(EWMS(,宽度=2,EWS)),-时间%>%
解组()
##A tible:7×4
#时间组值值1
#                 
#1 b-0.6264538 0.7383247
#2 b 0.1209979 0.6496139
#3 b-0.8235288-0.2404270
#4 1 a 1.5952808 1.5117812
#5 2 a 0.4890359 0.5410213
#6.3 a-0.7715648-0.5671385
#7.4 a 0.4102726-2.2714137


可能有帮助。您的预期输出表明您希望在延迟中使用原始值,而不是更新的值。您的
数据$value[3]
与您的断言不匹配。如果它应该脱离先前值的更新版本,则
$value[1]
为-0.626,
$value[2]
0.184+0.1(-0.626)
或0.121,
$value[3]
-0.836+0.1(0.121)
或-0.824(不是0.817)。@MikeH。谢谢你抓住了这个机会!我在代码和期望的输出中修正了一点疏忽@佩曼,最后一行不是也错了吗?可能有帮助。您的预期输出表明您希望在延迟中使用原始值,而不是更新的值。您的
数据$value[3]
与您的断言不匹配。如果它应该脱离先前值的更新版本,则
$value[1]
为-0.626,
$value[2]
0.184+0.1(-0.626)
或0.121,
$value[3]
-0.836+0.1(0.121)
或-0.824(不是0.817)。@MikeH。谢谢你抓住了这个机会!我在代码和期望的输出中修正了一点疏忽@佩曼最后一行不是也错了吗?@r2evans我使用的是dplyr版本的
lag
。我一直在用它。我认为这是正确的,因为我得到的结果与OP所期望的完全相同。我在发送评论后意识到这是相同的。我认为要么OP断言陈述错误,要么期望的输出不正确。无论如何,在澄清之前,我将收回我的评论:-)@r2evans道歉!我修复的代码/操作中有一点疏忽it@PLapointe谢谢你的帮助!正如我提到的,所需的输出将使用最后更新的行!知道如何在函数中引用它吗?@r2evans我使用的是dplyr版本的
lag
。我一直在用它。我认为这是正确的,因为我得到的结果与OP所期望的完全相同。我在发送评论后意识到这是相同的。我认为要么OP断言陈述错误,要么期望的输出不正确。无论如何,在澄清之前,我将收回我的评论:-)@r2evans道歉!我修复的代码/操作中有一点疏忽it@PLapointe谢谢你的帮助!正如我提到的,所需的输出将使用最后更新的行!你知道如何在函数中引用它吗?太棒了。谢谢@r2evans提供的非常灵活的解决方案!我一直在寻找一种定制移动平均线的方法,这帮了我很大的忙!!太棒了。感谢@r2evans提供了非常灵活的解决方案!我一直在寻找一种定制移动平均线的方法,这帮了我很大的忙!!
library(dplyr)
dat %>%
  group_by(groups) %>%
  mutate_each(funs(EWMS(., width=2, EWS)), -time) %>%
  ungroup()
# # A tibble: 7 × 4
#    time groups      value     value1
#   <int>  <chr>      <dbl>      <dbl>
# 1     1      b -0.6264538  0.7383247
# 2     2      b  0.1209979  0.6496139
# 3     3      b -0.8235288 -0.2404270
# 4     1      a  1.5952808  1.5117812
# 5     2      a  0.4890359  0.5410213
# 6     3      a -0.7715648 -0.5671385
# 7     4      a  0.4102726 -2.2714137