#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 могут быть быстрее. Возможно, я слишком много думаю