Создайте имена групп для последовательных значений

Выглядит как простая задача, не могу придумать более простой способ. у меня естьx вектор ниже, и необходимо создать имена групп для последовательных значений. Моя попытка использовалаrle, лучшие идеи?

# data
x <- c(1,1,1,2,2,2,3,2,2,1,1)

# make groups
rep(paste0("Group_", 1:length(rle(x)$lengths)), rle(x)$lengths)
# [1] "Group_1" "Group_1" "Group_1" "Group_2" "Group_2" "Group_2" "Group_3" "Group_4"
# [9] "Group_4" "Group_5" "Group_5"
 Joseph Wood14 июн. 2016 г., 15:12
Хорошая попытка. Ключевая строка в исходном кодеrle используетdiff как @Roland сделал ниже.
 zx875414 июн. 2016 г., 12:19
@MamounBenghezal, пожалуйста, сначала проверьте ожидаемый результат1 этоGroup_1и последний1 этоGroup_5
 Mamoun Benghezal14 июн. 2016 г., 12:18
почему не использовать пасту напрямую?paste0('groupe_', c(1,1,1,2,2,2,3,2,2,1,1))
 Carl Witthoft14 июн. 2016 г., 16:07
Но .. сделав это, как вы наносите на карту этиGroup_x имена для фактических значений и длины пробега? То есть, в чем смысл этого упражнения?
 Sotos14 июн. 2016 г., 12:18
потому что последние две группы будут 2 и 1 вместо 4 и 5, если вставить напрямую
 zx875414 июн. 2016 г., 16:12
Имена @CarlWitthoft находятся в том же порядке, что и значения, поэтому прямая карта, т.е.names(x) <- myGroups, Мои фактические данные - data.frame, поэтому я могу применить то же самое и создатьGroup столбец для агрегатных функций вниз по линии.

Ответы на вопрос(3)

Используя cumsum, но не полагаясь на числовые данные:

paste0("Group_", 1 + c(0, cumsum(x[-length(x)] != x[-1])))


[1] "Group_1" "Group_1" "Group_1" "Group_2" "Group_2" "Group_2" "Group_3" "Group_4" "Group_4" "Group_5" "Group_5"

С помощьюrleid отdata.table,

library(data.table)

paste0('Group_', rleid(x))
 #[1] "Group_1" "Group_1" "Group_1" "Group_2" "Group_2" "Group_2" "Group_3" "Group_4" "Group_4" "Group_5" "Group_5"
Решение Вопроса

С помощьюdiff а такжеcumsum :

paste0("Group_", cumsum(c(1, diff(x) != 0)))
#[1] "Group_1" "Group_1" "Group_1" "Group_2" "Group_2" "Group_2" "Group_3" "Group_4" "Group_4" "Group_5" "Group_5"

(Если ваши значения являются значениями с плавающей запятой, вам, возможно, придется избегать!= и используйте вместо этого допуск.)

 Roland14 июн. 2016 г., 12:40
abs(diff(x)) < tol сtol основанный наhelp(".Machine").
 zx875414 июн. 2016 г., 12:39
Мои числа не имеют плавающих точек, поэтому!= должно быть в порядке, но что вы подразумеваете под толерантностью?
 Carl Witthoft14 июн. 2016 г., 16:08
Хорошо, я предполагаю, что это быстрее, чемrle(x) и обработки выходных данных от этого. OTOH, я хотел бы знать, как сопоставить имена групп с прогонами, в этом случае можно также использоватьrle(x)$lengths .
 thelatemail14 июн. 2016 г., 12:33
Если они не могут быть числовыми -paste0("Group_", cumsum(c(TRUE, head(x,-1)!=tail(x,-1))))

Ваш ответ на вопрос