我有这个数据帧。
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)))