使用dplyr更容易计算变量的变化?

时间:2015-10-05 19:34:19

标签: r dplyr

我正在尝试使用dplyr找到一种更简单的方法来计算数据框中变量(由列表示)的变化。我的玩具数据集是这样的

structure(list(CAR = structure(c(1L, 2L, 3L, 4L, 5L, 6L, 1L, 
2L, 3L, 4L, 5L, 6L, 1L, 2L, 3L, 4L, 5L, 6L), .Label = c("a", 
"b", "c", "d", "e", "f"), class = "factor"), TIME = c(0L, 0L, 
0L, 0L, 0L, 0L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L
), VAR = c(20L, 30L, 40L, 50L, 60L, 70L, 30L, 40L, 50L, 60L, 
70L, 80L, 40L, 50L, 60L, 70L, 80L, 90L)), .Names = c("CAR", "TIME", 
"VAR"), class = "data.frame", row.names = c(NA, -18L))

看起来像

   CAR TIME VAR
1    a    0  20
2    b    0  30
3    c    0  40
4    d    0  50
5    e    0  60
6    f    0  70
7    a    1  30
8    b    1  40
9    c    1  50
10   d    1  60
11   e    1  70
12   f    1  80
13   a    2  40
14   b    2  50
15   c    2  60
16   d    2  70
17   e    2  80
18   f    2  90

我正在尝试计算VAR之间的变化TIME等于0和其他时间,例如,每个1,2 CAR

这就是我所做的,这似乎是一种非常复杂的方式,首先我得到VAR的值TIME等于0

library(dplyr)
X <- local_test %>% filter(TIME == 0)  %>% group_by(CAR)  %>% mutate(baseline_VAR = VAR)

X看起来像

Source: local data frame [6 x 4]
Groups: CAR

  CAR TIME VAR baseline_VAR
1   a    0  20           20
2   b    0  30           30
3   c    0  40           40
4   d    0  50           50
5   e    0  60           60
6   f    0  70           70

然后,我使用原始数据框left_join

进行local_test
Y  <- left_join(local_test, X, by = c("CAR"))

Y看起来像

   CAR TIME.x VAR.x TIME.y VAR.y baseline_VAR
1    a      0    20      0    20           20
2    b      0    30      0    30           30
3    c      0    40      0    40           40
4    d      0    50      0    50           50
5    e      0    60      0    60           60
6    f      0    70      0    70           70
7    a      1    30      0    20           20
8    b      1    40      0    30           30
9    c      1    50      0    40           40
10   d      1    60      0    50           50
11   e      1    70      0    60           60
12   f      1    80      0    70           70
13   a      2    40      0    20           20
14   b      2    50      0    30           30
15   c      2    60      0    40           40
16   d      2    70      0    50           50
17   e      2    80      0    60           60
18   f      2    90      0    70           70

最后,我在Y中添加了一列,用于计算VAR之间TIME的变化CAR

Y %>% group_by(CAR) %>% mutate(change_VAR = VAR.x - baseline_VAR)

最终Y看起来像

Source: local data frame [18 x 7]
Groups: CAR

   CAR TIME.x VAR.x TIME.y VAR.y baseline_VAR change_VAR
1    a      0    20      0    20           20          0
2    b      0    30      0    30           30          0
3    c      0    40      0    40           40          0
4    d      0    50      0    50           50          0
5    e      0    60      0    60           60          0
6    f      0    70      0    70           70          0
7    a      1    30      0    20           20         10
8    b      1    40      0    30           30         10
9    c      1    50      0    40           40         10
10   d      1    60      0    50           50         10
11   e      1    70      0    60           60         10
12   f      1    80      0    70           70         10
13   a      2    40      0    20           20         20
14   b      2    50      0    30           30         20
15   c      2    60      0    40           40         20
16   d      2    70      0    50           50         20
17   e      2    80      0    60           60         20
18   f      2    90      0    70           70         20

这似乎是一项额外的工作,在原始数据框中添加了额外的列。我需要重复对大数据帧执行此操作。是否有更简单(一步)的方式来计算change_VAR

谢谢!

2 个答案:

答案 0 :(得分:4)

这可以通过采用“VAR&#39; VAR”的区别来实现。使用min&#39; VAR&#39;按&#39; CAR&#39;分组。

local_test %>%
     group_by(CAR) %>%
     mutate(change_VAR= VAR- min(VAR))

或者如果&#39; VAR&#39;的基值?是时候&#39;时间&#39;是0(假设每个组没有重复的&#39; TIME&#39;)我们将“&#39; VAR&#39;对于TIME 0并获得差异。

local_test %>% 
      group_by(CAR) %>%
      mutate(change_VAR= VAR- VAR[TIME==0])

答案 1 :(得分:3)

group_by(DF, CAR) %>%
  arrange(CAR, TIME) %>%
  mutate(change_VAR = VAR-VAR[1]) %>%
  ungroup() %>%
  arrange(TIME, CAR)

我做了一点安排akrun,但我不假设数据是在前面正确订购的。安排也确保最早的观察位于每组的第1位。

编辑: 如果你对这种事感兴趣。这是我和Akrun的答案之间的速度比较。 (简答,和Akrun一起去)

microbenchmark(
  akrun1 =  DF %>%
              group_by(CAR) %>%
              mutate(change_VAR= VAR- min(VAR)),
  akrun2 = DF %>% 
             group_by(CAR) %>%
             mutate(change_VAR= VAR- VAR[TIME==0]),
  Benjamin = group_by(DF, CAR) %>%
               arrange(CAR, TIME) %>%
               mutate(change_VAR = VAR-VAR[1]) %>%
               ungroup() %>%
               arrange(TIME, CAR))
unit: microseconds
     expr      min        lq      mean   median        uq      max neval cld
   akrun1  887.360  903.1950  975.6354  930.467  954.5125 3246.223   100  a 
   akrun2  888.240  901.1425  947.5220  913.899  952.7530 3002.536   100  a 
 Benjamin 1584.697 1604.7835 1720.8034 1662.993 1692.1705 3765.561   100   b