检查值是否在组dplyr中随时间变化

时间:2019-11-13 16:14:14

标签: group-by dplyr tidyverse

我有一个类似的df:

# A tibble: 14 x 3
   user_id flag  order
     <dbl> <chr> <dbl>
 1       1 aaa       1
 2       1 aaa       2
 3       1 aaa       3
 4       1 bbb       4
 5       2 bbb       1
 6       2 bbb       2
 7       3 aaa       1
 8       3 aaa       2
 9       3 bbb       3
10       4 ccc       1
11       4 aaa       2
12       4 aaa       3
13       4 aaa       4
14       4 aaa       5



test_df <- tibble::tribble(
             ~user_id, ~flag, ~order,
                    1, "aaa",      1,
                    1, "aaa",      2,
                    1, "aaa",      3,
                    1, "bbb",      4,
                    2, "bbb",      1,
                    2, "bbb",      2,
                    3, "aaa",      1,
                    3, "aaa",      2,
                    3, "bbb",      3,
                    4, "ccc",      1,
                    4, "aaa",      2,
                    4, "aaa",      3,
                    4, "aaa",      4,
                    4, "aaa",      5)
  • user_id:每个用户的唯一标识符
  • 标志(字符串)
  • 订购

我想检查每个user_id的标志是否已更改顺序。

我想创建一列has_changed,值:

  • has_changed,如果标志在bbb的值从1开始是!=后更改为order

我做到了:

test_df %>%
  group_by(user_id) %>%
  mutate(has_changed = ifelse(any(flag == 'bbb' & order != 1), 'yes','no'))

结果:

# A tibble: 14 x 4
# Groups:   user_id [4]
   user_id flag  order has_changed
     <dbl> <chr> <dbl> <chr>      
 1       1 aaa       1 yes        
 2       1 aaa       2 yes        
 3       1 aaa       3 yes        
 4       1 bbb       4 yes        
 5       2 bbb       1 yes        
 6       2 bbb       2 yes        
 7       3 aaa       1 yes        
 8       3 aaa       2 yes        
 9       3 bbb       3 yes        
10       4 ccc       1 no         
11       4 aaa       2 no         
12       4 aaa       3 no         
13       4 aaa       4 no         
14       4 aaa       5 no    

给我一​​个错误的结果,因为user_id == 2并没有改变,因为它一直带有标志bbb

我想要的输出应如下所示:

# A tibble: 14 x 4
   user_id flag  order has_changed
     <dbl> <chr> <dbl> <chr>      
 1       1 aaa       1 yes        
 2       1 aaa       2 yes        
 3       1 aaa       3 yes        
 4       1 bbb       4 yes        
 5       2 bbb       1 no         
 6       2 bbb       2 no         
 7       3 aaa       1 yes        
 8       3 aaa       2 yes        
 9       3 bbb       3 yes        
10       4 ccc       1 no         
11       4 aaa       2 no         
12       4 aaa       3 no         
13       4 aaa       4 no         
14       4 aaa       5 no  

2 个答案:

答案 0 :(得分:0)

如果我理解您的问题,则希望标识user_id,以便对于order == 1,您拥有flag != bbb,并且在随后的order != 1,您也{{1 }}。

如果我们阐明这个逻辑,我们就写

flag == bbb

产生

library(tidyverse)

test_df %>%
  group_by(user_id) %>%
  mutate(first_bbb = any(flag != 'bbb' & order == 1),
         subsequent_not_bbb = any(flag == 'bbb' & order != 1),
         has_changed = if_else(first_bbb & subsequent_not_bbb, 'yes', 'no'))

# A tibble: 14 x 6 # Groups: user_id [4] user_id flag order first_bbb subsequent_not_bbb has_changed <dbl> <chr> <dbl> <lgl> <lgl> <chr> 1 1 aaa 1 TRUE TRUE yes 2 1 aaa 2 TRUE TRUE yes 3 1 aaa 3 TRUE TRUE yes 4 1 bbb 4 TRUE TRUE yes 5 2 bbb 1 FALSE TRUE no 6 2 bbb 2 FALSE TRUE no 7 3 aaa 1 TRUE TRUE yes 8 3 aaa 2 TRUE TRUE yes 9 3 bbb 3 TRUE TRUE yes 10 4 ccc 1 TRUE FALSE no 11 4 aaa 2 TRUE FALSE no 12 4 aaa 3 TRUE FALSE no 13 4 aaa 4 TRUE FALSE no 14 4 aaa 5 TRUE FALSE no 列符合所需的输出。您当然可以通过管道插入has_changed来完全重现所需的输出。另外,这是一个更简洁的版本(如果可读性较差):

select(user_id, flag, order, has_changed)

给出

library(tidyverse)

test_df %>%
  group_by(user_id) %>%
  mutate(has_changed = if_else(any(flag != 'bbb' & order == 1) & any(flag == 'bbb' & order != 1), 'yes', 'no'))

根据需要。

答案 1 :(得分:0)

对于 user_id,如果有 any 值的 flag 值为 'bbb' 而先前的值不是 'bbb' 则返回 {{1} } 为组,否则返回 'yes'

'no'