如何使用mutate()生成依赖于其他新变量的先前行值的变量?

时间:2019-05-03 20:08:13

标签: r dplyr data-manipulation mutate

我正在尝试使用dplyr的{​​{1}}函数来创建新变量,这些新变量取决于后续新变量的前一行值。

我已经用不同的术语搜索了SO,以查看是否有点击的声音,而最接近的答案是this。这是我所用的mutate()的粗略结构:

tib

我想使用library(dplyr) library(magrittr) tib <- tribble( ~ID, "A1", "A2", "A3", "A4", "A5", "A1", "B1", "B2", "B3" ) 来生成列mutate()xy

z

例如,对于上面显示的值,我希望输出为:

tib %<>%
  mutate(
    x = if_else(ID == "A1", 2, lag(y) + lag(z)),
    y = if_else(ID == "A1", 3, x + lag(z)),
    z = if_else(ID == "A1", 7, lag(z))
  )

此方法的问题是| ID | x | y | z | -------------------------------- | A1 | 2 | 3 | 7 | | A2 | 10 | 17 | 7 | | A3 | 24 | 31 | 7 | | A4 | 38 | 45 | 7 | | A5 | 52 | 59 | 7 | | A1 | 2 | 3 | 7 | | B1 | 10 | 17 | 7 | | B2 | 24 | 31 | 7 | | B3 | 38 | 45 | 7 | -------------------------------- 返回错误:

mutate()

我了解在启动Error in lag(y) : object 'y' not found y之前先参考它们。如果z是一个仅依赖于自身的事物(如上面的链接问题所示),我可以按照建议的那样多次通过,但是我认为这不可能。

如我的问题注释中所建议,如果我尝试初始化这些值(以便知道xy),如下所示,

z

我收到的小词如下:

tib %<>%
  mutate(
    x = if_else(ID == "A1", 2, 0),
    y = if_else(ID == "A1", 3, 0),
    z = if_else(ID == "A1", 7, 0)
  )

tib %<>%
  mutate(
    x = if_else(ID == "A1", 2, lag(y) + lag(z)),
    y = if_else(ID == "A1", 3, x + lag(z)),
    z = if_else(ID == "A1", 7, lag(z))
  )

这与我预期的结果有所不同(也许是因为# A tibble: 9 x 4 ID x y z <chr> <dbl> <dbl> <dbl> 1 A1 2 3 7 2 A2 10 17 7 3 A3 0 0 0 4 A4 0 0 0 5 A5 0 0 0 6 A1 2 3 7 7 B1 10 17 7 8 B2 0 0 0 9 B3 0 0 0 按列计算所有变量,所以mutate()yz)?

希望更明确地说,我希望能够根据所述列的前几行中存在的值来为每个新列计算值-它们总是会有一些行会获得初始值,但是如何使它流到较低的行?

如果有帮助,请在Excel中使用this is how I would want it to work(我刚刚开始学习R)。

我想继续使用0来保持代码的一致性。

1 个答案:

答案 0 :(得分:2)

mutate()不适用于Excel等迭代公式。它按列进行操作,因此在每一行迭代之间进行通信并不容易。在这种情况下,您的函数具有简单的非递归定义。这是包装非迭代版本的包装器函数

my_mutate <- function(data, x0, y0, z0) {
  mutate(data, 
    n = 1:n(),
    x = if_else(n==1, x0, y0 + z0*(n-1)),
    y = if_else(n==1, y0, y0 + z0*2*(n-1)),
    z = z0,
    n = NULL
  )
}

然后我们可以使用

执行组内转换
tib %>% group_by(grp=cumsum(ID=="A1")) %>% 
  my_mutate(x0=2, y0=3, z0=7) %>% 
  ungroup %>% select(-grp)
#   ID        x     y     z
#   <chr> <dbl> <dbl> <dbl>
# 1 A1        2     3     7
# 2 A2       10    17     7
# 3 A3       17    31     7
# 4 A4       24    45     7
# 5 A5       31    59     7
# 6 A1        2     3     7
# 7 B1       10    17     7
# 8 B2       17    31     7
# 9 B3       24    45     7

使用非迭代定义时要容易得多。