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