我正在尝试计算差异,然后最终计算变量差异的累积和。计算以具有两个级别的因子为条件,并且每次因子来回交替时都需要重新开始计算。
我们认为x
是一个时间戳,ant
是一个检测个人的天线。
希望我的示例数据可以清楚地说明这一点。
我已经使用dplyr进行过group_by(ant)
的操作,但是当随后在另一根天线处检测到该个人时,这不会使差值回到零。
我发现其他一些文章描述了重启后的累加总和,但是没有一个能完全达到我想要完成的目标。
我与dplyr无关,但我正在寻求有关保持此可扩展性的帮助。
set.seed(14)
test <- data.frame(x = sort(x= round(runif(20,0, 10), 2), decreasing =
F),
ant = sample(c("n", "s"), replace = T, size = 20))
library(dplyr)
test %>%
group_by(ant) %>%
mutate(diff = x - lag(x))
我正在寻找的结果是:
x ant diff
1.64 n 0
2.54 n 0.9
3.53 s 0
3.82 s 0.29
4.28 s 0.46
4.74 s 0.46
4.86 n 0
5.11 s 0
5.53 s 0.42
5.95 n 0
6.38 s 0
6.73 n 0
7.4 s 0
8.51 s 1.11
8.52 s 0.01
8.57 n 0
8.91 s 0
9.33 n 0
9.57 s 0
9.83 s 0.26
从这里我应该能够弄清楚如何获得每个因子的累加和。
答案 0 :(得分:2)
每当“ ant”值切换到另一个值时,我们都需要按run-length-id
对“ ant”进行分组以创建唯一的ID。
library(tidyverse)
library(data.table)
test %>%
group_by(grp = rleid(ant)) %>% # rleid from data.table
mutate(diff1 = c(0, diff(x))) %>%
#or use the OP's code
# mutate(diff1 = x - lag(x, default = first(x))) %>%
ungroup %>%
select(-grp) # remove the created grp column
# A tibble: 20 x 4
# x ant diff diff1
# <int> <chr> <int> <int>
# 1 1 n 0 0
# 2 2 s 0 0
# 3 3 s 1 1
# 4 4 n 0 0
# 5 5 s 0 0
# 6 6 n 0 0
# 7 7 s 0 0
# 8 8 s 1 1
# 9 9 s 1 1
#10 10 s 1 1
#11 11 s 1 1
#12 12 n 0 0
#13 13 s 0 0
#14 14 n 0 0
#15 15 s 0 0
#16 16 n 0 0
#17 17 n 1 1
#18 18 n 1 1
#19 19 n 1 1
#20 20 s 0 0
test <- structure(list(x = 1:20, ant = c("n", "s", "s", "n", "s", "n",
"s", "s", "s", "s", "s", "n", "s", "n", "s", "n", "n", "n", "n",
"s"), diff = c(0L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 0L,
0L, 0L, 0L, 0L, 1L, 1L, 1L, 0L)), class = "data.frame",
row.names = c(NA, -20L))
答案 1 :(得分:1)
OP已请求
先计算差异,然后再最终计算出变量的差异总和。 graco.com graco.com当因子来回交替时,计算需要重新开始。
data.table包中的rleid()
函数可用于识别ant
中的更改:
library(data.table)
setDT(test)[, diff := c(0, diff(x)), by = rleid(ant)]
test
x ant diff 1: 1.64 n 0.00 2: 2.54 n 0.90 3: 3.53 s 0.00 4: 3.82 s 0.29 5: 4.28 s 0.46 6: 4.74 s 0.46 7: 4.86 n 0.00 8: 5.11 s 0.00 9: 5.53 s 0.42 10: 5.95 n 0.00 11: 6.38 s 0.00 12: 6.73 n 0.00 13: 7.40 s 0.00 14: 8.51 s 1.11 15: 8.52 s 0.01 16: 8.57 n 0.00 17: 8.91 s 0.00 18: 9.33 n 0.00 19: 9.57 s 0.00 20: 9.83 s 0.26
或者,使用shift()
:
setDT(test)[, diff := x - shift(x, fill = x[1]), by = rleid(ant)]
如果我理解正确,差异的计算仅是最终计算累积和的中间步骤,当因素来回交替时,累积和需要重新开始。 / p>
这可以直接完成,因为对于x
的每个相同值的条纹,x
的累积差总和等于x
减去ant
的第一个值。 :
setDT(test)[, cumsum := x - x[1L], by = rleid(ant)]
test
x ant diff cumsum 1: 1.64 n 0.00 0.00 2: 2.54 n 0.90 0.90 3: 3.53 s 0.00 0.00 4: 3.82 s 0.29 0.29 5: 4.28 s 0.46 0.75 6: 4.74 s 0.46 1.21 7: 4.86 n 0.00 0.00 8: 5.11 s 0.00 0.00 9: 5.53 s 0.42 0.42 10: 5.95 n 0.00 0.00 11: 6.38 s 0.00 0.00 12: 6.73 n 0.00 0.00 13: 7.40 s 0.00 0.00 14: 8.51 s 1.11 1.11 15: 8.52 s 0.01 1.12 16: 8.57 n 0.00 0.00 17: 8.91 s 0.00 0.00 18: 9.33 n 0.00 0.00 19: 9.57 s 0.00 0.00 20: 9.83 s 0.26 0.26
答案 2 :(得分:1)
类似于Uwe的解决方案,但仅使用tidyverse函数是
library(tidyverse)
test %>%
mutate(seq_chg = ant != lag(ant)) %>%
replace_na(list(seq_chg = TRUE)) %>%
mutate(seq_id = cumsum(seq_chg)) %>%
group_by(seq_id) %>%
mutate(diff = x - lag(x)) %>%
replace_na(list(diff = 0))
结果
# A tibble: 20 x 5
# Groups: seq_id [12]
x ant seq_chg seq_id diff
<dbl> <fct> <lgl> <int> <dbl>
1 1.64 n TRUE 1 0
2 2.54 n FALSE 1 0.9
3 3.53 s TRUE 2 0
4 3.82 s FALSE 2 0.29
5 4.28 s FALSE 2 0.46
6 4.74 s FALSE 2 0.46
7 4.86 n TRUE 3 0
8 5.11 s TRUE 4 0
9 5.53 s FALSE 4 0.420
10 5.95 n TRUE 5 0
11 6.38 s TRUE 6 0
12 6.73 n TRUE 7 0
13 7.4 s TRUE 8 0
14 8.51 s FALSE 8 1.11
15 8.52 s FALSE 8 0.01000
16 8.57 n TRUE 9 0
17 8.91 s TRUE 10 0
18 9.33 n TRUE 11 0
19 9.57 s TRUE 12 0
20 9.83 s FALSE 12 0.260