计算两级因子交替时重新开始的差异

时间:2019-01-18 21:55:53

标签: r dataframe dplyr

我正在尝试计算差异,然后最终计算变量差异的累积和。计算以具有两个级别的因子为条件,并且每次因子来回交替时都需要重新开始计算。

我们认为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

从这里我应该能够弄清楚如何获得每个因子的累加和。

3 个答案:

答案 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当因子来回交替时,计算需要重新开始。

计算差异

包中的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