Совокупная сумма, основанная на соответствующих последних значениях подгруппы

#r #dataframe

#r #фрейм данных

Вопрос:

У меня есть фрейм данных:

 DF <- data.frame(Observation = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
                 ID          = c('A','A','B','C','D','D','B','B','B','B','A','A','A','B','D','D','C'),
                 Group       = c('X1','X2','X1','X1','X2','X2','X2','X1','X1','X2','X2','X2','X2','X1','X2','X1','X1'),
                 Value       = c(1,0,1,0,0,1,1,1,0,0,1,1,0,1,0,1,1))
 

Я хотел бы получить совокупную сумму по «идентификатору» (не сложно), но только на основе соответствующих последних значений «Группы», частью которой является каждый идентификатор. Другими словами: для каждого «идентификатора» создайте совокупную сумму для всех последних доступных значений тех «групп», где присутствует идентификатор (может включать текущее значение в заданной строке с учетом ссылки на последнее доступное значение).

Подробное объяснение: пример для ID = A:

In ( 1 ) ID = A ссылается на X1 in ( 1 ) со значением = 1 , приводит к cum_sum = 1 .

In ( 2 ) ID = A ссылается на X1 in ( 1 ) со значением = 1 и X2 in ( 2 ) со значением = 0 , приводит к cum_sum = 1 .

In ( 11 ) ID = A ссылается на X1 in ( 1 ) со значением = 1 и X2 in ( 11 ) со значением = 1 , приводит к cum_sum = 2 .

In ( 12 ) ID = A ссылается на X1 in ( 1 ) со значением = 1 и X2 in ( 12 ) со значением = 1 , приводит к cum_sum = 2 .

In ( 13 ) ID = A ссылается на X1 in ( 1 ) со значением = 1 и X2 in ( 13 ) со значением = 0 , приводит к cum_sum = 1 .

Конечный результат выглядит следующим образом.

 DF_Result <- data.frame(Observation = c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
                        ID          = c('A','A','B','C','D','D','B','B','B','B','A','A','A','B','D','D','C'),
                        Group       = c('X1','X2','X1','X1','X2','X2','X2','X1','X1','X2','X2','X2','X2','X1','X2','X1','X1'),
                        Value       = c(1,0,1,0,0,1,1,1,0,0,1,1,0,1,0,1,1),
                        Cum_Sum     = c(1,1,1,0,0,1,2,2,1,0,2,2,1,1,0,1,1))
 

Заранее большое вам спасибо.

Комментарии:

1. Да, пакеты и базовые функции уже известны — но это не просто кумулятивная сумма, основанная на одном идентификаторе — это кумулятивная сумма по идентификатору для каждого последнего значения группы (группы), частью которой или которой является идентификатор

2. @Ronak Shah Спасибо. Может быть (много) других групп (это упрощенный пример).

3. Я думаю, что логика не ясна, когда я смотрю на разные «идентификаторы»

4. например, для ID = «B» значение изменилось с 2 на 1 (строка с 8 по 9) — оба равны X1, а значение равно 1 и 0. Вы вычли это. Аналогично 9-10, это 0, в то время как предыдущее значение X2 равно 2

5. @akrun. Вы правы. Правильная версия: в (6) ID = D ссылается на X2 в (6) со значением = 1, приводит к cum_sum = 1. Пожалуйста, извинитесь за ошибку.

Ответ №1:

Согласен с некоторыми другими, что объяснения немного сложны для понимания… Но вот моя попытка: вы имеете в виду, что пытаетесь вычислить сумму для каждого идентификатора для каждого идентификатора и кумулятивного последнего значения для каждой группы?

Если да, то вот реализация. Хитрость заключается в том, чтобы вычислить производную для каждого идентификатора и для каждой группы (например diff() ), и они принимают ее cumsum() для каждого идентификатора:

 DF %>% 
  group_by(ID, Group) %>% 
  mutate(Diff = Value - lag(Value, default=0)) %>% 
  group_by(ID) %>% 
  mutate(Cum_Sum = cumsum(Diff))
 

Комментарии:

1. Спасибо, Пьер. Похоже, это работает отлично (также для N> 2 групп). В настоящее время я тестирую несколько модификаций (на данный момент это работает, как и ожидалось). Отлично!

2. Отлично. Дайте нам знать, если вам нужны какие-либо изменения

3. Да, работает с дополнительными подгруппами, а также с изменениями значения по умолчанию. Я предполагаю, что cumsum может быть заменен любой дальнейшей операцией (например, mean), верно? В любом случае, отлично!

Ответ №2:

Я согласен с мнением, выраженным в комментариях, что это неясно. Честно говоря (и я действительно не имею в виду это как оскорбление), это ужасное описание проблемы с неоднозначными / нестандартными терминами («ссылаться на») и запутанными объяснениями.

Возможно, следующее является шагом к поиску решения; оно не полностью воспроизводит ваш ожидаемый результат, но приближается. Надеюсь, вы действительно допустили ошибку в своем ожидаемом результате, потому что, честно говоря, я не могу разобраться в логике.

 DF %>%
    group_by(ID) %>%
    mutate(
        n = 1:n(),
        Cum_Sum = if_else(n > 1, Value   first(Value), Value)) %>%
    select(-n)
## A tibble: 17 x 5
## Groups:   ID [4]
#   Observation ID    Group Value Cum_Sum
#         <dbl> <fct> <fct> <dbl>   <dbl>
# 1           1 A     X1        1       1
# 2           2 A     X2        0       1
# 3           3 B     X1        1       1
# 4           4 C     X1        0       0
# 5           5 D     X2        0       0
# 6           6 D     X2        1       1
# 7           7 B     X2        1       2
# 8           8 B     X1        1       2
# 9           9 B     X1        0       1
#10          10 B     X2        0       1
#11          11 A     X2        1       2
#12          12 A     X2        1       2
#13          13 A     X2        0       1
#14          14 B     X1        1       2
#15          15 D     X2        0       0
#16          16 D     X1        1       1
#17          17 C     X1        1       1
 

Я перевел вашу постановку задачи следующим образом: Cum_Sum это сумма текущего Value и первого значения в этом Group ; если текущее значение является первым значением, Cum_Sum это просто текущее Value .

Первые 9 строк идентичны вашему ожидаемому результату; Я понятия не имею, почему Cum_Sum для строки 10 равно 0…


Обновить

Надеюсь, приближаясь к тому, что вы пытаетесь сделать

 DF %>%
    group_by(ID) %>%
    mutate(Cum_Sum = Value   lag(Value, default = 0))
## A tibble: 17 x 5
## Groups:   ID [4]
#   Observation ID    Group Value Cum_Sum
#         <dbl> <fct> <fct> <dbl>   <dbl>
# 1           1 A     X1        1       1
# 2           2 A     X2        0       1
# 3           3 B     X1        1       1
# 4           4 C     X1        0       0
# 5           5 D     X2        0       0
# 6           6 D     X2        1       1
# 7           7 B     X2        1       2
# 8           8 B     X1        1       2
# 9           9 B     X1        0       1
#10          10 B     X2        0       0
#11          11 A     X2        1       1
#12          12 A     X2        1       2
#13          13 A     X2        0       1
#14          14 B     X1        1       1
#15          15 D     X2        0       1
#16          16 D     X1        1       1
#17          17 C     X1        1       1
 

При условии, что я правильно понял вашу «логику», это действительно не имеет ничего общего с кумулятивной суммой; вместо этого это просто

введите описание изображения здесь

за ID .

Если вы хотите сделать это за ID и за Group , просто замените group_by(ID) на group_by(ID, Group) .

Комментарии:

1. Значение в позиции 10 равно 0 вместо 1 (на основе DF_Result

2. @akrun Да, к сожалению:-) Я понятия не имею, почему (см. Последнее предложение моего поста)… надеемся, что OP допустил ошибку или, возможно, это поможет прояснить проблему.

3. Кроме того, для 14 у меня есть сомнения, которые я высказал в комментариях

4. Спасибо. Пожалуйста, прочитайте примеры, которые я разместил под исходными сообщениями: В (10) ID = B относится к X1 в (9) со значением = 0 и X2 в (10) со значением = 0, приводит к cum_sum = 0. В (14) ID = B относится к X1 в (14) со значением = 1 и X2 в (10) со значением = 0, приводит к cum_sum = 1. (Всегда последнее доступное значение для соответствующих подгрупп).

5. @Dan Да, конечно, но вашим комментариям несколько не хватает конкретной логики, которую нам нужно понять. Подумайте об этом. 4-5 человек пытались это сделать (и многие другие, не признавая). Итак, было бы неплохо сформулировать логику немного иначе