Повторяющаяся последовательность чисел для каждого идентификатора, где длина идентификатора неравна

#r

#r

Вопрос:

У меня есть фрейм данных, подобный следующему.

 df <- data.frame(id = c(rep("aa", 4), rep("bb", 7), rep("cc", 10)), value = runif(21))
  

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

     id  value       group
1   aa  0.1986791   1
2   aa  0.2356943   2
3   aa  0.2748867   3
4   aa  0.5913211   4
5   bb  0.2533907   1
6   bb  0.1234872   2
7   bb  0.2299059   3
8   bb  0.5975753   4
9   bb  0.2114086   1
10  bb  0.4637012   2
11  bb  0.6471012   3
12  cc  0.9605731   1
13  cc  0.6763982   2
14  cc  0.445148    3
15  cc  0.3577738   4
16  cc  0.4557315   1
17  cc  0.445414    2
18  cc  0.2450926   3
19  cc  0.6943507   4
20  cc  0.412237    1
21  cc  0.3277259   2
  

Я надеюсь, что ответ должен выглядеть как; rep(seq(1,4), by="id" . Фрейм данных довольно большой, а длина идентификатора варьируется от 1 до 9500. Есть ли базовое решение r для этого?
Спасибо

Ответ №1:

Вы можете использовать ave для повторения 1: 4 по группам :

 df$group <- with(df, ave(value, id, FUN = function(x) 
                     rep(1:4, length.out = length(x))))
df

#   id    value group
#1  aa 0.710182     1
#2  aa 0.000625     2
#3  aa 0.475317     3
#4  aa 0.220119     4
#5  bb 0.379817     1
#6  bb 0.612771     2
#7  bb 0.351798     3
#8  bb 0.111135     4
#9  bb 0.243619     1
#10 bb 0.668056     2
#11 bb 0.417647     3
#12 cc 0.788196     1
#13 cc 0.102865     2
#14 cc 0.434893     3
#15 cc 0.984957     4
#16 cc 0.893051     1
#17 cc 0.886469     2
#18 cc 0.175053     3
#19 cc 0.130696     4
#20 cc 0.653102     1
#21 cc 0.343516     2
  

Вы также можете использовать dplyr и data.table с той же логикой.

 library(dplyr)
library(data.table)
#dplyr
df %>% group_by(id) %>% mutate(group = rep(1:4, length.out = n()))

#data.table
setDT(df)[, group := rep(1:4, length.out = .N), id]
  

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

1. Спасибо @Ronak Shah. Решение data.table намного быстрее, чем базовое решение.

Ответ №2:

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

 library(data.table)
setDT(df)[, group :=  (rowid(id)-1) %% 4   1]