我如何模仿新行的拖动功能,例如 Excel 但对于 R?
How do I mimic the drag functionality for new rows such as in Excel but for R?
我对 lead()
和 lag()
感到有些不安,它们没有为每个填充行拖动 dynamically/sequentially。
我的愿望是根据初始值填充新行,然后根据先前填充的行顺序填充下一行。在 Excel 中,这可以通过在单元格中声明 formula/function 并拖动它来完成。我如何在 R 中执行此操作?
见下例
x y z
<dbl> <dbl> <dbl>
1 1 1 1
2 2 3 NA
3 3 5 NA
4 4 7 NA
5 5 9 NA
6 6 11 NA
7 7 13 NA
8 8 15 NA
9 9 17 NA
10 10 19 NA
所需的输出遵循此计算,其中 t-1
是先前值的下标:
Z = Z_t-1 + X_t-1 - Y_t-1
.
期望的输出
x y z
<dbl> <dbl> <dbl>
1 1 1 1
2 2 3 1
3 3 5 0
4 4 7 -2
5 5 9 -6
6 6 11 -12
7 7 13 -18
8 8 15 -25
9 9 17 -33
10 10 19 -42
如评论中所述,预期的输出与指定的公式不匹配。在tidyverse
中,可以用accumulate
进行递归操作
library(purrr)
library(dplyr)
df1 %>%
mutate(z = unlist(accumulate2(x, y, ~ ..1 + ..2 - ..3,
.init = first(z))[-(n()+1)]))
-输出
x y z
1 1 1 1
2 2 3 1
3 3 5 0
4 4 7 -2
5 5 9 -5
6 6 11 -9
7 7 13 -14
8 8 15 -20
9 9 17 -27
10 10 19 -35
数据
df1 <- structure(list(x = 1:10, y = c(1L, 3L, 5L, 7L, 9L, 11L, 13L,
15L, 17L, 19L), z = c(1L, NA, NA, NA, NA, NA, NA, NA, NA, NA)),
class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"))
请注意,您问题中的预期结果与您描述的公式的输出不匹配。
在这种特定情况下,您可以使用 cumsum
(累计和)得到答案:
cumsum(df1$x - df1$y + 1)
[1] 1 1 0 -2 -5 -9 -14 -20 -27 -35
但是,一般来说,如果你想根据前面结果的输出递归地应用一个函数,你需要写一个循环来做(或者使用一个函数“在幕后”使用循环,如 akrun 用 accumulate
所示)。实现结果的基本 R 中的一个简单循环是:
for(i in 2:nrow(df1)) df1$z[i] <- df1$z[i-1] + df1$x[i-1] - df1$y[i-1]
df
#> x y z
#> 1 1 1 1
#> 2 2 3 1
#> 3 3 5 0
#> 4 4 7 -2
#> 5 5 9 -5
#> 6 6 11 -9
#> 7 7 13 -14
#> 8 8 15 -20
#> 9 9 17 -27
#> 10 10 19 -35
当您可以使用像 cumsum
这样的函数时,它使用基于 C 的矢量化而不是 R 中的循环,这可能是一个更有效的解决方案。
我对 lead()
和 lag()
感到有些不安,它们没有为每个填充行拖动 dynamically/sequentially。
我的愿望是根据初始值填充新行,然后根据先前填充的行顺序填充下一行。在 Excel 中,这可以通过在单元格中声明 formula/function 并拖动它来完成。我如何在 R 中执行此操作?
见下例
x y z
<dbl> <dbl> <dbl>
1 1 1 1
2 2 3 NA
3 3 5 NA
4 4 7 NA
5 5 9 NA
6 6 11 NA
7 7 13 NA
8 8 15 NA
9 9 17 NA
10 10 19 NA
所需的输出遵循此计算,其中 t-1
是先前值的下标:
Z = Z_t-1 + X_t-1 - Y_t-1
.
期望的输出
x y z
<dbl> <dbl> <dbl>
1 1 1 1
2 2 3 1
3 3 5 0
4 4 7 -2
5 5 9 -6
6 6 11 -12
7 7 13 -18
8 8 15 -25
9 9 17 -33
10 10 19 -42
如评论中所述,预期的输出与指定的公式不匹配。在tidyverse
中,可以用accumulate
library(purrr)
library(dplyr)
df1 %>%
mutate(z = unlist(accumulate2(x, y, ~ ..1 + ..2 - ..3,
.init = first(z))[-(n()+1)]))
-输出
x y z
1 1 1 1
2 2 3 1
3 3 5 0
4 4 7 -2
5 5 9 -5
6 6 11 -9
7 7 13 -14
8 8 15 -20
9 9 17 -27
10 10 19 -35
数据
df1 <- structure(list(x = 1:10, y = c(1L, 3L, 5L, 7L, 9L, 11L, 13L,
15L, 17L, 19L), z = c(1L, NA, NA, NA, NA, NA, NA, NA, NA, NA)),
class = "data.frame", row.names = c("1",
"2", "3", "4", "5", "6", "7", "8", "9", "10"))
请注意,您问题中的预期结果与您描述的公式的输出不匹配。
在这种特定情况下,您可以使用 cumsum
(累计和)得到答案:
cumsum(df1$x - df1$y + 1)
[1] 1 1 0 -2 -5 -9 -14 -20 -27 -35
但是,一般来说,如果你想根据前面结果的输出递归地应用一个函数,你需要写一个循环来做(或者使用一个函数“在幕后”使用循环,如 akrun 用 accumulate
所示)。实现结果的基本 R 中的一个简单循环是:
for(i in 2:nrow(df1)) df1$z[i] <- df1$z[i-1] + df1$x[i-1] - df1$y[i-1]
df
#> x y z
#> 1 1 1 1
#> 2 2 3 1
#> 3 3 5 0
#> 4 4 7 -2
#> 5 5 9 -5
#> 6 6 11 -9
#> 7 7 13 -14
#> 8 8 15 -20
#> 9 9 17 -27
#> 10 10 19 -35
当您可以使用像 cumsum
这样的函数时,它使用基于 C 的矢量化而不是 R 中的循环,这可能是一个更有效的解决方案。