Я пытаюсь вычислить текущий счетчик (т. Е. Кумулятивную сумму), который зависит от других переменных и может сбрасываться для определенных значений другой переменной. Я работаю в R и предпочел бы решение на основе dplyr
, если это возможно.
Я хочу создать переменную для текущего счета, cumulative
, на основе следующего алгоритма:
- Рассчитайте текущий счетчик (
cumulative
) в комбинацияхid
иage
- Увеличивать текущий счетчик (
cumulative
) на 1 для каждого последующегоtrial
, гдеaccuracy = 0
,block = 2
иcondition = 1
- Сбросьте текущий счетчик (
cumulative
) на 0 для каждогоtrial
, гдеaccuracy = 1
,block = 2
иcondition = 1
, и следующее приращение возобновится с 1 (не предыдущее число) - Для каждого
trial
, гдеblock != 2
илиcondition != 1
, оставьте текущий счетчик (cumulative
) какNA
Вот минимальный рабочий пример:
mydata <- data.frame(id = c(1,1,1,1,1,1,1,1,1,1,1),
age = c(1,1,1,1,1,1,1,1,1,1,2),
block = c(1,1,2,2,2,2,2,2,2,2,2),
trial = c(1,2,1,2,3,4,5,6,7,8,1),
condition = c(1,1,1,1,1,2,1,1,1,1,1),
accuracy = c(0,0,0,0,0,0,0,1,0,0,0)
)
id age block trial condition accuracy
1 1 1 1 1 0
1 1 1 2 1 0
1 1 2 1 1 0
1 1 2 2 1 0
1 1 2 3 1 0
1 1 2 4 2 0
1 1 2 5 1 0
1 1 2 6 1 1
1 1 2 7 1 0
1 1 2 8 1 0
1 2 2 1 1 0
Ожидаемый выход:
id age block trial condition accuracy cumulative
1 1 1 1 1 0 NA
1 1 1 2 1 0 NA
1 1 2 1 1 0 1
1 1 2 2 1 0 2
1 1 2 3 1 0 3
1 1 2 4 2 0 NA
1 1 2 5 1 0 4
1 1 2 6 1 1 0
1 1 2 7 1 0 1
1 1 2 8 1 0 2
1 2 2 1 1 0 1
2 ответа
Мы можем использовать case_when
, чтобы присвоить значение, которое нам нужно, в зависимости от наших условий. Затем мы добавляем дополнительное условие group_by
, используя cumsum
для переключения значений, когда temp
столбец 0. На последнем этапе mutate
мы временно replace
{{X6} } значения в temp
равны 0, затем возьмите cumsum
над ним и снова верните значения NA
на свое место, чтобы получить окончательный результат.
library(dplyr)
mydata %>%
group_by(id, age) %>%
mutate(temp = case_when(accuracy == 0 & block == 2 & condition == 1 ~ 1,
accuracy == 1 & block == 2 & condition == 1 ~ 0,
TRUE ~ NA_real_)) %>%
ungroup() %>%
group_by(id, age, group = cumsum(replace(temp == 0, is.na(temp), 0))) %>%
mutate(cumulative = replace(cumsum(replace(temp, is.na(temp), 0)),
is.na(temp), NA)) %>%
select(-temp, -group)
# group id age block trial condition accuracy cumulative
# <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0 1 1 1 1 1 0 NA
# 2 0 1 1 1 2 1 0 NA
# 3 0 1 1 2 1 1 0 1
# 4 0 1 1 2 2 1 0 2
# 5 0 1 1 2 3 1 0 3
# 6 0 1 1 2 4 2 0 NA
# 7 0 1 1 2 5 1 0 4
# 8 1 1 1 2 6 1 1 0
# 9 1 1 1 2 7 1 0 1
#10 1 1 1 2 8 1 0 2
#11 1 1 2 2 1 1 0 1
Вот вариант с использованием data.table
. Создайте двоичный столбец на основе match
значений paste
d "точность", "блок", "условие" с пользовательскими значениями, сгруппированными по идентификатору длины прогона двоичного столбца. ('ind'), 'id' и 'age', получите совокупную сумму 'ind' и назначьте (:=
) ее новому столбцу ('Cumulative')
library(data.table)
setDT(mydata)[, ind := match(do.call(paste0, .SD), c("121", "021")) - 1,
.SDcols = c("accuracy", "block", "condition")
][, Cumulative := cumsum(ind), .(rleid(ind), id, age)
][, ind := NULL][]
# id age block trial condition accuracy Cumulative
# 1: 1 1 1 1 1 0 NA
# 2: 1 1 1 2 1 0 NA
# 3: 1 1 2 1 1 0 1
# 4: 1 1 2 2 1 0 2
# 5: 1 1 2 3 1 0 3
# 6: 1 1 2 4 2 0 NA
# 7: 1 1 2 5 1 1 0
# 8: 1 1 2 6 1 0 1
# 9: 1 1 2 7 1 0 2
#10: 1 2 2 1 1 0 1
Похожие вопросы
Новые вопросы
r
R - это бесплатный язык программирования с открытым исходным кодом и программная среда для статистических вычислений, биоинформатики, визуализации и общих вычислений. Пожалуйста, предоставьте минимальные и воспроизводимые примеры вместе с желаемым результатом. Используйте dput () для данных и укажите все небазовые пакеты с вызовами library (). Не вставляйте изображения для данных или кода, вместо этого используйте блоки кода с отступом. По вопросам, связанным со статистикой, используйте https://stats.stackexchange.com.