您如何检查一组操作的顺序,为每个操作指定等级



我有这个数据帧。

user    action    date        rank
AAA     jump      2018-01-01  1
AAA     climb     2018-01-02  2
AAA     leap      2018-01-03  3
BBB     jump      2018-01-01  1
BBB     climb     2018-01-03  2
BBB     leap      2018-01-05  3
BBB     gallop    2018-01-08  4
CCC     leap      2018-01-01  1
CCC     climb     2018-01-02  2
CCC     gallop    2018-01-04  3

它执行操作并根据日期按升序为每个用户添加排名。

我想找到以错误顺序执行操作的任何用户。订单应jump -> climb -> leap -> gallop

输出将是CCC,因为该用户在攀登之前确实跳跃了。

user   
CCC

如何引用特定行?我正在使用dplyr,我可以按每个用户对其进行分组并为每个用户添加排名,row_number(),但我不知道如何制定规则来检查操作是否以正确的顺序发生。

注意 - 我意识到这不清楚。并非每个用户都执行所有操作,但顺序仍然很重要。

这就是我迄今为止的工作

badData <- NULL
for (i in df$user){
  filtered <- filter(df, user == i)
  first <- ifelse(filtered[filtered$action == "jump",]$rank > 1, TRUE, FALSE)
  second <- ifelse(filtered[filtered$action == "climb",]$rank < filtered[filtered$action == "jump",]$rank, TRUE, FALSE)
  #and so on for the rest of the rules
  if(first + second > 0) badData <- c(badData, i)   
}
如果将

action作为因子并使用 levels 参数设置顺序,则可以按用户分组,然后使用 is.unsorted 测试操作是否未排序:

library(dplyr)
df %>%
  mutate(action = factor(action, levels = c("jump", "climb", "leap", "gallop"))) %>%
  group_by(user) %>%
  filter(is.unsorted(action)) %>%
  pull(user) %>%
  unique
[1] "CCC"

这里有一个小例子,你可以实现这一点。首先创建一个包含正确顺序的引用数据帧(refdata(。然后,您可以轻松使用tidyverse包:

mydata <- tibble(id = rep(c("aaa", "bbb", "ccc"), each = 4), action = letters[c(1:4, 1,2 ,4, 3, 4,1,2,3)],
       date = rep(1:3, 4)) 
refdata <- tibble(action = letters[1:4], right_order = 1:4)

mydata %>% left_join(refdata, by = "action") %>% group_by(id) %>% 
  summarise(test = identical(right_order, sort(right_order)))

最新更新