В R создайте последовательный столбец от 1 до N на основе значений в других столбцах

#r #dplyr #data-manipulation

#r #dplyr #манипулирование данными

Вопрос:

Кажется простой проблемой манипулирования данными, однако мы хотели бы избежать использования цикла for, который просто сравнивает значения в каждой строке. У нас есть следующий фрейм данных:

 zed = data.frame(
  a = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1),
  b = c('a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd', 'd', 'd', 'd', 'e', 'e', 'a', 'a'),
  c = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 1, 1),
  stringsAsFactors = FALSE
)

output = zed = data.frame(
  a = c(1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 1, 1),
  b = c('a', 'a', 'b', 'b', 'b', 'c', 'c', 'd', 'd', 'd', 'd', 'd', 'e', 'e', 'a', 'a'),
  c = c(1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 1, 1),
  group = c(1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 7, 8, 8, 9, 9),
  stringsAsFactors = FALSE
)

> output
   a b c group
1  1 a 1     1
2  1 a 1     1
3  1 b 1     2
4  1 b 1     2
5  1 b 1     2
6  1 c 1     3
7  1 c 2     4
8  1 d 2     5
9  2 d 2     6
10 2 d 2     6
11 2 d 2     6
12 2 d 3     7
13 2 e 3     8
14 2 e 3     8
15 1 a 1     9
16 1 a 1     9
 

Фрейм данных начинается со столбцов a , b , c , и нам нужно добавить group столбец в фрейм данных. group Столбец начинается с 1 и последовательно увеличивается, если какое-либо из значений в a , b , c отличается от их значения в предыдущей строке.

Это не так просто, как выполнить group_by() on a , b , c , поскольку одна и та же строка может появиться позже, но не последовательно, в фрейме данных (например, строки 1,2 == строки 15,16, однако они не совпадают group , потому что они не появлялись последовательно в фрейме данных).

Ответ №1:

Мы можем использовать

 library(data.table)
setDT(zed)[, group := .GRP, .(rleid(a, b, c))]
 

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

1. zed не обязательно должна быть таблицей данных. Вы можете просто сделать zed$group <- data.table::rleidv(zed)

2. Знаете ли вы какие-либо преимущества по сравнению с этой опцией: library(data.table); setDT(zed)[, group := rleid(a, b, c)][] ? ( 1 )

3. @markus Ваш подход или подход AllanCameron могут быть быстрее. Возможно, я слишком много думаю