У меня есть набор данных, где каждая строка указывает на одно правильное/неправильное взаимодействие участника. Я хотел бы подсчитать количество неправильных взаимодействий, пока участник дважды не зарегистрирует правильный ответ.
Мой фрейм данных выглядит так:
id = c(1,1,1,1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3)
accuracy = c(0,1,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,1)
timestamp = c(2405.078,2409.575,2414.239,2419.084,2424.138,2428.510,805.5845,812.2674,817.6420,822.5424,828.0416,832.9703,842.2013,456.9943,463.0222,469.0649,475.2177,480.3976,486.9402,491.5632,497.0068)
df <-data.frame(id, accuracy, timestamp)
Я думал об использовании функции rle, но не знаю, как добавить условие. Мне нужно будет создать новую переменную, которая даст мне количество попыток, пока условие не будет выполнено.
Это должно выглядеть примерно так:
В идеале я бы добавил еще один столбец, который рассчитывает время, затраченное до достижения условия с метками времени. Спасибо за помощь!
Я бы сделал это изначально:
df |> dplyr::mutate(tworight = cumsum(accuracy) >1,
time_to_tworight = min(timestamp[tworight]) - min(timestamp),
wrongs_til_tworight = min(cumsum(accuracy == 0)[tworight]),
.by = id)
дает:
id accuracy timestamp tworight time_to_tworight wrongs_til_tworight
1 1 0 2405.0780 FALSE 19.0600 3
2 1 1 2409.5750 FALSE 19.0600 3
3 1 0 2414.2390 FALSE 19.0600 3
4 1 0 2419.0840 FALSE 19.0600 3
5 1 1 2424.1380 TRUE 19.0600 3
6 1 1 2428.5100 TRUE 19.0600 3
7 2 1 805.5845 FALSE 22.4571 3
8 2 0 812.2674 FALSE 22.4571 3
9 2 0 817.6420 FALSE 22.4571 3
10 2 0 822.5424 FALSE 22.4571 3
11 2 1 828.0416 TRUE 22.4571 3
12 2 1 832.9703 TRUE 22.4571 3
13 2 1 842.2013 TRUE 22.4571 3
14 3 0 456.9943 FALSE 34.5689 5
15 3 0 463.0222 FALSE 34.5689 5
16 3 0 469.0649 FALSE 34.5689 5
17 3 0 475.2177 FALSE 34.5689 5
18 3 0 480.3976 FALSE 34.5689 5
19 3 1 486.9402 FALSE 34.5689 5
20 3 1 491.5632 TRUE 34.5689 5
21 3 1 497.0068 TRUE 34.5689 5
@caeco — обновлен номер строки
Сначала выберите строки до двух правильных ответов, включая второй правильный ответ, если он существует (отсюда и lag
).
Затем подведите итоги, принимая во внимание случай, когда второго правильного ответа не удалось достичь (тогда time_spent
будет NA
).
df %>%
group_by(id) %>%
mutate(count = lag(cumsum(accuracy))) %>%
filter(is.na(count) | count <= 1) %>%
select(-count) %>%
summarize(
n = sum(accuracy == 0),
time_spent = ifelse(
n() - n == 2,
tail(timestamp, 1) - timestamp[[1]],
NA)
)
Другой подход с использованием cumsum
внутри каждой группы. При этом будет использоваться slice
для сохранения строк до тех пор, пока не будет достигнута сумма 2 для accuracy
. Затем в reframe
будет подсчитано количество рядов и рассчитана разница во времени для каждого id
. Результат будет другим, если меньше 2 accuracy
(неясно, какой вывод должен быть в этом случае, если это возможно). Кроме того, чтобы подсчитать неправильные ответы до тех пор, пока не будут достигнуты 2 правильных ответа, можно вычесть 2 из количества строк.
library(tidyverse)
df |>
slice(
seq_len(which.max(cumsum(accuracy) >= 2)),
.by = id
) |>
reframe(
trial_count = n(),
time_spent = last(timestamp) - first(timestamp),
.by = id
)
Или с более старой версией пакетов tidyverse:
df %>%
group_by(id) %>%
slice(seq_len(which.max(cumsum(accuracy) >= 2))) %>%
summarise(
trial_count = n(),
time_spent = last(timestamp) - first(timestamp)
)
Выход
id trial_count time_spent
1 1 5 19.0600
2 2 5 22.4571
3 3 7 34.5689
Спасибо! У меня не установлена новейшая версия r, я обменял |> на %>%. Он выдает мне сообщение о том, что не может найти функцию «reframe», хотя я загружаю dplyr и tidyverse. Думаете это связано с обновлением?
@caeco Посмотрите отредактированный ответ и попробуйте использовать summarise
и group_by
, как указано выше, без встроенного канала. Это работает?
Привет спасибо! Это помогает вычислить время, но моя основная проблема заключается в том, чтобы придумать условие, при котором строки подсчитываются до тех пор, пока значение TRUE не будет зарегистрировано дважды для каждого идентификатора. Есть ли у вас какие-либо предложения, как я мог бы это сделать?