#r
#r
Вопрос:
У меня есть этот фрейм данных.
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)
}
Ответ №1:
Если вы создаете 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"
Комментарии:
1. Это чертовски радикально. Действительно классная штука, такого раньше не видел.
2. Извините, я откатил ‘принятый ответ’, потому что не у каждого пользователя есть все действия. Некоторые пользователи могут просто прыгать и скакать, но порядок все еще имеет значение. Я должен был упомянуть об этом.
3. ХОРОШО — это все равно будет работать, даже если набор действий неполон. Или вы хотите отметить тех, у кого неправильный порядок или неполный набор действий?
4. Вы правы, это все еще работает. Итак,
is.unsorted()
не возражает, если есть значения, которых у него нет, он просто проверяет, что значения, которые у него есть, находятся в правильном порядке?5. Да,
pull()
делает именно это. Это также причина, по которой я использовалunique()
вместоdistinct()
, посколькуdistinct()
это не работает с векторами.
Ответ №2:
Вот небольшой пример, на котором вы можете этого добиться. Сначала вы создаете фрейм данных refrence ( 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)))