Как я могу подсчитать значение предыдущих строк до тех пор, пока не будет достигнут критерий?

У меня есть набор данных, где каждая строка указывает на одно правильное/неправильное взаимодействие участника. Я хотел бы подсчитать количество неправильных взаимодействий, пока участник дважды не зарегистрирует правильный ответ.

Мой фрейм данных выглядит так:

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, но не знаю, как добавить условие. Мне нужно будет создать новую переменную, которая даст мне количество попыток, пока условие не будет выполнено.

Это должно выглядеть примерно так:

ИДЕНТИФИКАТОР пробный_счет 1 5 2 5 3 4

В идеале я бы добавил еще один столбец, который рассчитывает время, затраченное до достижения условия с метками времени. Спасибо за помощь!

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
70
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Я бы сделал это изначально:

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

Привет спасибо! Это помогает вычислить время, но моя основная проблема заключается в том, чтобы придумать условие, при котором строки подсчитываются до тех пор, пока значение TRUE не будет зарегистрировано дважды для каждого идентификатора. Есть ли у вас какие-либо предложения, как я мог бы это сделать?

caeco 09.04.2024 13:19

@caeco — обновлен номер строки

PGSA 09.04.2024 13:35

Сначала выберите строки до двух правильных ответов, включая второй правильный ответ, если он существует (отсюда и 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 09.04.2024 14:20

@caeco Посмотрите отредактированный ответ и попробуйте использовать summarise и group_by, как указано выше, без встроенного канала. Это работает?

Ben 09.04.2024 14:34

Другие вопросы по теме