Заполнение значений на основе сигналов в столбцах

#r

#r

Вопрос:

В приведенных ниже данных я хочу увеличивать значения ячеек после каждого 1, но сбрасывать его на ноль в следующей ячейке, если Z.out = 1. Вот пример.

Начальные данные:

 Z   B_1 C_1 D_1 E_1 F_1
0   0   0   0   0   0
0   1   0   0   1   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   1   0   0   0
0   0   0   0   0   0
1   0   0   0   0   0
0   0   0   0   0   1
0   1   0   0   0   0
0   0   1   1   0   0
0   0   0   1   0   0
0   1   0   1   0   0
0   0   0   0   0   0
0   0   0   0   0   0
0   0   0   0   0   0
1   0   0   0   0   0
0   0   0   0   1   0
0   0   0   0   0   0
  

Желаемый результат:

 Z   B_1 C_1 D_1 E_1 F_1
0   0   0   0   0   0
0   1   0   0   1   0
0   1   0   0   1   0
0   1   0   0   1   0
0   1   0   0   1   0
0   1   1   0   1   0
0   1   1   0   1   0
1   1   1   0   1   0
0   0   0   0   0   1
0   1   0   0   0   1
0   1   1   1   0   1
0   1   1   2   0   1
0   2   1   3   0   1
0   2   1   3   0   1
0   2   1   3   0   1
0   2   1   3   0   1
1   2   1   3   0   1
0   0   0   0   1   0
0   0   0   0   1   0
  

Я думаю, что могу использовать df <- df %>% transmute_at(vars(contains(«_1»)),) чтобы настроить таргетинг на нужные столбцы и заменить их желаемым результатом, но я не нашел правильного синтаксиса для функциональной части transmute . Я пытаюсь использовать cumsum() для переноса значений по каждому столбцу, но когда я пытаюсь перевернуть обратно на основе z.out, я просто заканчиваю с ошибками.

Спасибо за помощь!

Ответ №1:

Одной dplyr из возможностей может быть:

 df %>%
 group_by(grp = cumsum(Z == 0 amp; lag(Z, default = first(Z)) == 1)) %>%
 mutate(across(-Z, cumsum))

      Z   B_1   C_1   D_1   E_1   F_1   grp
   <int> <int> <int> <int> <int> <int> <int>
 1     0     0     0     0     0     0     0
 2     0     1     0     0     1     0     0
 3     0     1     0     0     1     0     0
 4     0     1     0     0     1     0     0
 5     0     1     0     0     1     0     0
 6     0     1     1     0     1     0     0
 7     0     1     1     0     1     0     0
 8     1     1     1     0     1     0     0
 9     0     0     0     0     0     1     1
10     0     1     0     0     0     1     1
11     0     1     1     1     0     1     1
12     0     1     1     2     0     1     1
13     0     2     1     3     0     1     1
14     0     2     1     3     0     1     1
15     0     2     1     3     0     1     1
16     0     2     1     3     0     1     1
17     1     2     1     3     0     1     1
18     0     0     0     0     1     0     2
19     0     0     0     0     1     0     2
  

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

1. Итак, это работает для приведенного примера, но когда mutate(across(-Z, cumsum) вы исключаете только Z по имени. Что, если я хочу исключить любое количество других столбцов? или я бы просто как-то включил целевые столбцы A_1 — F1?

2. Я не знаю ваш реальный набор данных, но вы можете включать / исключать переменные, используя помощники выбора, такие как starts_with() или ends_with() .

3. Спасибо, я просто немного поиграл с этим и попросил пользователя contains("_1") сделать это, и, похоже, это сработало. Приветствия!

Ответ №2:

Аналогично подходу tmfmnk, также работает следующее:

 df %>% 
  group_by(grp = c(0, lag(cumsum(diff(Z) == 1), 1, 0))) %>% 
  mutate(across(-Z, cumsum)) %>% 
  ungroup()