我有以下功能为一列中的变量构建一个库存效果。该变量在B列中创建一个值,该值采用ColumnA中的值,并在B列中的先前观察中添加一个结转(例如0.5)。
constructZ <- function(lag, N) {
r <- lag^(seq_len(N)-1)
m <- matrix(rep(r,N),nrow=N)
z <- matrix(0,nrow=N,ncol=N)
z[lower.tri(z,diag=TRUE)] <- m[row(m) <= (N+1-col(m))]
z
}
我现在的问题是,我有一个面板数据集,在一个列中有许多不同情况的观察结果。每个案例都有一个特定的指标(数字)。数据如下:
ColumnA Indicator Time
1 1 1
0 1 2
0 1 3
4 2 1
5 2 2
0 2 3
4 3 1
0 3 2
2 3 3
我现在希望将函数应用于所有观察的每个案例(指标)(时间)。
知道怎么做到这一点?输出应该如下:
ColumnA Indicator Time ColumnB
1 1 1 1
0 1 2 0.5
0 1 3 0.25
4 2 1 4
5 2 2 7
0 2 3 3.5
4 3 1 4
0 3 2 2
2 3 3 3
非常感谢任何帮助或支持!
非常感谢提前!
答案 0 :(得分:0)
这是我的代码。
library(dplyr) # Optional, but makes code cleaner
raw = data.frame(ColumnA =
c(1, 0, 0, 4, 5, 0, 4, 0, 2),
Indicator =
rep(x = 1:3, each = 3),
Time = 1:3)
factor = 0.5
loop = function(vec) {
length = length(x = vec)
if (length == 1) {
return(vec)
}
if (length == 2) {
return(vec + c(0, vec[2] * factor))
}
for (idx in 2:length) {
vec[idx] = vec[idx] + vec[idx - 1] * factor
}
return(vec)
}
output = raw %>%
mutate(ColumnB =
tapply(X = ColumnA,
INDEX = Indicator,
FUN = loop) %>%
unlist())
output
答案 1 :(得分:0)
这是一种替代的无循环/功能编程解决方案。我们将使用Reduce()
函数,该函数对向量中的每对项应用二元函数。
例如,Reduce(`+`, xs)
计算向量中的值的总和。如果我们设置accumulate = TRUE
,我们会获得滚动/累积总和。
Reduce(`+`, 1:6)
#> [1] 21
# What Reduce is doing here, basically
((((((1) + 2) + 3) + 4) + 5) + 6)
#> [1] 21
# Keep each intermediate sum
Reduce(`+`, 1:6, accumulate = TRUE)
#> [1] 1 3 6 10 15 21
(purrr包将这两种行为分为不同的功能:reduce()
和accumulate()
。)
我们可以使用Reduce()
来实现结转/缩放功能。首先,定义一个对一对值起作用的函数,然后使用Reduce()
来执行它的滚动版本。
rolling_scale <- function(xs, scale_factor) {
scale_pair <- function(x1, x2) x2 + scale_factor * x1
Reduce(scale_pair, xs, accumulate = TRUE)
}
rolling_scale(c(4, 5, 0), .5)
#> [1] 4.0 7.0 3.5
现在,我们可以使用dplyr并将此滚动功能应用于每个指标组。
library(dplyr)
raw <- data.frame(
ColumnA = c(1, 0, 0, 4, 5, 0, 4, 0, 2),
Indicator = rep(x = 1:3, each = 3),
Time = 1:3)
raw %>%
group_by(Indicator) %>%
mutate(ColumnB = rolling_scale(ColumnA, .5)) %>%
ungroup()
#> # A tibble: 9 × 4
#> ColumnA Indicator Time ColumnB
#> <dbl> <int> <int> <dbl>
#> 1 1 1 1 1.00
#> 2 0 1 2 0.50
#> 3 0 1 3 0.25
#> 4 4 2 1 4.00
#> 5 5 2 2 7.00
#> 6 0 2 3 3.50
#> 7 4 3 1 4.00
#> 8 0 3 2 2.00
#> 9 2 3 3 3.00