如何使用accumulate函数来计算2个相互交织的变量
How to use accumulate function to calculate 2 intertwining variables
亲爱的朋友/老师/各位R用户,大家好,
一段时间以来,我一直在考虑使用 purrr
中的 accumulate
函数族,最近我遇到了一个非常棘手的情况,我们想计算 2 个新函数每一行的变量,我们必须使用另一行来计算每一行。这是我的数据集(这是我看到的另一个问题的摘录):
structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA,
1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17,
8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15,
17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0,
0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df",
"tbl", "data.frame"))
我想要的输出是这样的:
Scenario SlNo A B C E
<dbl> <int> <dbl> <dbl> <dbl> <dbl>
1 0 NA NA NA 4 6
2 1 1 14 19 32 1
3 1 5 1 13 35 -2
4 1 9 17 20 40.5 10.5
5 1 13 8 7 42.8 -0.25
6 1 17 10 16 42.1 8.12
7 1 21 9 12 46.2 8.19
8 1 25 14 18 54.3 22.3
9 1 29 14 15 69.4 34.4
10 1 33 4 17 91.1 58.1
我们当然可以使用for循环来计算从第二行到最后一行的变量C
和E
的值。这样做的好处是我可以在每次迭代中同时填充两个变量,例如使用 E
的当前值来计算 C
的当前值,反之亦然:
for(i in 2:nrow(df)) {
df$C[i] <- if_else(df$Scenario[i] != 0, (1-0.5) * df$C[i-1] + 3 + 2 + df$B[i] + df$E[i-1],
df$C[i])
df$E[i] <- if_else(df$Scenario[i] != 0, df$C[i] + df$B[i] - 50, df$E[i])
}
df
所以我很感激 accumulate
有一些关于如何将它应用到这类问题的解决方案。
非常感谢您
在这种情况下,我们需要同时生成两个输出列;并在一个输入列的帮助下迭代并给定两个输出列的两个初始值。现在,purrr::accumulate
通常基于一个输入在一个输出上工作,而 purrr::accumulate2()
在 2 个输入上再次工作一个输出。因此,相反,我的累积策略详述如下:-
为了进一步参考,您可能还会看到此 answer 在 purrr::accumulate
中同时使用甚至超过 2 个参数(输入值)生成了多个结果
- 我假设您的第一行只是在列的剩余值中输入 first/initial 值。
- 要在
accumulate
中有多个输出,您可以使这个函数 purrr::accumulate
(我必须说是很棒的函数)作为生成小标题而不是向量。
- 我删除了第一行。
- 在
.init
参数中使用了您的初始值
- 创建了
tibble
格式的输出
- 使用的语法
tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E, E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50)
- 如果仔细观察,
C
是用给定的公式生成的。但是,
- 对于
E
我们需要生成(输出)值 C
因此,我使用 C
的公式而不是使用 .x
或 .y
- 最后,使用
unnest_wider
在 tidyr
中取消嵌套输出
library(tidyverse, warn.conflicts = F)
df <- structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA,
1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17,
8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15,
17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0,
0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df",
"tbl", "data.frame"))
df[1:4] %>%
filter(Scenario != 0) %>%
mutate(new = accumulate(B,
.init = tibble(C = 4, E = 6),
~ tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E,
E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50
)
)[-1]
) %>%
unnest_wider(new)
#> # A tibble: 9 x 6
#> Scenario SlNo A B C E
#> <dbl> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 14 19 32 1
#> 2 1 5 1 13 35 -2
#> 3 1 9 17 20 40.5 10.5
#> 4 1 13 8 7 42.8 -0.25
#> 5 1 17 10 16 42.1 8.12
#> 6 1 21 9 12 46.2 8.19
#> 7 1 25 14 18 54.3 22.3
#> 8 1 29 14 15 69.4 34.4
#> 9 1 33 4 17 91.1 58.1
由 reprex package (v2.0.0)
于 2021-07-05 创建
这是一个 base R 解决方案:
df[, c("C", "E")] <- do.call(rbind, Reduce(function(x, y) {
data.frame(C = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]],
E = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]] + df$B[y] - 50)
}, init = data.frame(C = 4, E = 6), 2:nrow(df), accumulate = TRUE))
df
# A tibble: 10 x 6
Scenario SlNo A B C E
<dbl> <int> <dbl> <dbl> <dbl> <dbl>
1 0 NA NA NA 4 6
2 1 1 14 19 32 1
3 1 5 1 13 35 -2
4 1 9 17 20 40.5 10.5
5 1 13 8 7 42.8 -0.25
6 1 17 10 16 42.1 8.12
7 1 21 9 12 46.2 8.19
8 1 25 14 18 54.3 22.3
9 1 29 14 15 69.4 34.4
10 1 33 4 17 91.1 58.1
亲爱的朋友/老师/各位R用户,大家好,
一段时间以来,我一直在考虑使用 purrr
中的 accumulate
函数族,最近我遇到了一个非常棘手的情况,我们想计算 2 个新函数每一行的变量,我们必须使用另一行来计算每一行。这是我的数据集(这是我看到的另一个问题的摘录):
structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA,
1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17,
8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15,
17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0,
0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df",
"tbl", "data.frame"))
我想要的输出是这样的:
Scenario SlNo A B C E
<dbl> <int> <dbl> <dbl> <dbl> <dbl>
1 0 NA NA NA 4 6
2 1 1 14 19 32 1
3 1 5 1 13 35 -2
4 1 9 17 20 40.5 10.5
5 1 13 8 7 42.8 -0.25
6 1 17 10 16 42.1 8.12
7 1 21 9 12 46.2 8.19
8 1 25 14 18 54.3 22.3
9 1 29 14 15 69.4 34.4
10 1 33 4 17 91.1 58.1
我们当然可以使用for循环来计算从第二行到最后一行的变量C
和E
的值。这样做的好处是我可以在每次迭代中同时填充两个变量,例如使用 E
的当前值来计算 C
的当前值,反之亦然:
for(i in 2:nrow(df)) {
df$C[i] <- if_else(df$Scenario[i] != 0, (1-0.5) * df$C[i-1] + 3 + 2 + df$B[i] + df$E[i-1],
df$C[i])
df$E[i] <- if_else(df$Scenario[i] != 0, df$C[i] + df$B[i] - 50, df$E[i])
}
df
所以我很感激 accumulate
有一些关于如何将它应用到这类问题的解决方案。
非常感谢您
在这种情况下,我们需要同时生成两个输出列;并在一个输入列的帮助下迭代并给定两个输出列的两个初始值。现在,purrr::accumulate
通常基于一个输入在一个输出上工作,而 purrr::accumulate2()
在 2 个输入上再次工作一个输出。因此,相反,我的累积策略详述如下:-
为了进一步参考,您可能还会看到此 answer 在 purrr::accumulate
中同时使用甚至超过 2 个参数(输入值)生成了多个结果
- 我假设您的第一行只是在列的剩余值中输入 first/initial 值。
- 要在
accumulate
中有多个输出,您可以使这个函数purrr::accumulate
(我必须说是很棒的函数)作为生成小标题而不是向量。 - 我删除了第一行。
- 在
.init
参数中使用了您的初始值 - 创建了
tibble
格式的输出 - 使用的语法
tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E, E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50)
- 如果仔细观察,
C
是用给定的公式生成的。但是, - 对于
E
我们需要生成(输出)值C
因此,我使用C
的公式而不是使用.x
或.y
- 最后,使用
unnest_wider
在tidyr
中取消嵌套输出
library(tidyverse, warn.conflicts = F)
df <- structure(list(Scenario = c(0, 1, 1, 1, 1, 1, 1, 1, 1, 1), SlNo = c(NA,
1L, 5L, 9L, 13L, 17L, 21L, 25L, 29L, 33L), A = c(NA, 14, 1, 17,
8, 10, 9, 14, 14, 4), B = c(NA, 19, 13, 20, 7, 16, 12, 18, 15,
17), C = c(4, 0, 0, 0, 0, 0, 0, 0, 0, 0), E = c(6, 0, 0, 0, 0,
0, 0, 0, 0, 0)), row.names = c(NA, -10L), class = c("tbl_df",
"tbl", "data.frame"))
df[1:4] %>%
filter(Scenario != 0) %>%
mutate(new = accumulate(B,
.init = tibble(C = 4, E = 6),
~ tibble(C = (1 -0.5)* .x$C + 5 + .y + .x$E,
E = 0.5 * .x$C + 5 + .x$E + 2 * .y - 50
)
)[-1]
) %>%
unnest_wider(new)
#> # A tibble: 9 x 6
#> Scenario SlNo A B C E
#> <dbl> <int> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 14 19 32 1
#> 2 1 5 1 13 35 -2
#> 3 1 9 17 20 40.5 10.5
#> 4 1 13 8 7 42.8 -0.25
#> 5 1 17 10 16 42.1 8.12
#> 6 1 21 9 12 46.2 8.19
#> 7 1 25 14 18 54.3 22.3
#> 8 1 29 14 15 69.4 34.4
#> 9 1 33 4 17 91.1 58.1
由 reprex package (v2.0.0)
于 2021-07-05 创建这是一个 base R 解决方案:
df[, c("C", "E")] <- do.call(rbind, Reduce(function(x, y) {
data.frame(C = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]],
E = 0.5 * x[["C"]] + 5 + df$B[y] + x[["E"]] + df$B[y] - 50)
}, init = data.frame(C = 4, E = 6), 2:nrow(df), accumulate = TRUE))
df
# A tibble: 10 x 6
Scenario SlNo A B C E
<dbl> <int> <dbl> <dbl> <dbl> <dbl>
1 0 NA NA NA 4 6
2 1 1 14 19 32 1
3 1 5 1 13 35 -2
4 1 9 17 20 40.5 10.5
5 1 13 8 7 42.8 -0.25
6 1 17 10 16 42.1 8.12
7 1 21 9 12 46.2 8.19
8 1 25 14 18 54.3 22.3
9 1 29 14 15 69.4 34.4
10 1 33 4 17 91.1 58.1