我正在尝试使用dplyr
的mutate()
函数来创建新变量,这些新变量取决于后续新变量的前一行值。
我用不同的术语搜索了SO,以查看是否有点击声,而最接近的就是这个答案。这是tib
我的小标题的粗略结构:
library(dplyr)
library(magrittr)
tib <- tribble(
~ID,
"A1",
"A2",
"A3",
"A4",
"A5",
"A1",
"B1",
"B2",
"B3"
)
我想用mutate()
能够生成栏目x
,y
和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
我开始在他们面前。如果x
是像上面链接的问题中那样仅依赖于自身的事物,那么我可以按照那里的建议多次通过,但是我认为这不可能。
正如在评论我的问题的建议,如果我尝试初始化这些值(以便y
与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()
评估所有变量列明智所以y
和z
是0
)?
为了更清楚地说,我希望能够根据所述列的前几行中存在的值来计算每个新列的值-它们总是会有一些行,它们确实会获得初始值,但是如何我如何使其流向较低的行?
如果有帮助,这就是我希望它在Excel中工作的方式(我才刚刚开始学习R)。
我想继续使用dplyr
以保持代码的一致性。
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
当存在非迭代定义时,使用它们要容易得多。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句