Присвоить ИДЕНТИФИКАТОР колонке r последовательных групп

#r #dataframe #grouping #unique #cumulative-sum

#r #dataframe #группировка #уникальный #кумулятивная сумма

Вопрос:

Я хотел бы создать столбец в data.frame, который подсчитывает последовательный идентификатор групп (столбец s в фиктивном df)

 dummy_df = data.frame(s = c("a", "a", "b","b", "b", "c","c", "a", "a", "c", "c","a","a"),
                  desired_output= c(1,1,1,1,1,1,1,2,2,2,2,3,3))
dummy_df$rleid_output = rleid(dummy_df$s)
dummy_df
  
    s desired_output rleid_output
1  a              1            1
2  a              1            1
3  b              1            2
4  b              1            2
5  b              1            2
6  c              1            3
7  c              1            3
8  a              2            4
9  a              2            4
10 c              2            5
11 c              2            5
12 a              3            6
13 a              3            6
  

Я бы сказал, что это похоже на то, что rleid() делает, но перезапускает подсчет при появлении новой группы. Однако я не могу найти способ сделать это таким прямым способом. Спасибо.

Ответ №1:

Вы можете сделать:

 dummy_df$out <- with(rle(dummy_df$s), rep(ave(lengths, values, FUN = seq_along), lengths))
  

Результат:

    s desired_output out
1  a              1   1
2  a              1   1
3  b              1   1
4  b              1   1
5  b              1   1
6  c              1   1
7  c              1   1
8  a              2   2
9  a              2   2
10 c              2   2
11 c              2   2
12 a              3   3
13 a              3   3
  

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

1. Эй, я знаю, что делают rep и ave, но не могли бы вы объяснить, что делает этот код: rep(ave(длины, значения, FUN = seq_along)

2. rle() возвращает список из двух компонентов lengths и values , таким ave() seq_along() образом, возвращает инкрементный индекс для каждой группы.

Ответ №2:

Если вы готовы использовать data.table ( rleid является частью пакета), вы можете сделать это в два этапа следующим образом:

 library(data.table)
dummy_df = data.frame(s = c("a", "a", "b", "b", "b", "c", "c", "a", "a", "c", "c", "a", "a"))
# cast data.frame to data.table
setDT(dummy_df)
# create auxiliary variable
dummy_df[, rleid_output := rleid(s)]
# obtain desired output
dummy_df[, desired_output := rleid(rleid_output), by = "s"]
# end result
dummy_df
#>     s rleid_output desired_output
#>  1: a            1              1
#>  2: a            1              1
#>  3: b            2              1
#>  4: b            2              1
#>  5: b            2              1
#>  6: c            3              1
#>  7: c            3              1
#>  8: a            4              2
#>  9: a            4              2
#> 10: c            5              2
#> 11: c            5              2
#> 12: a            6              3
#> 13: a            6              3
  

Создано в 2020-10-16 годах пакетом reprex (версия 0.3.0)

Ответ №3:

вы можете попробовать a tidyverse в сочетании с базовой rle функцией R.

 library(tidyverse)
rle(dummy_df$s) %>% 
  with(., data.frame(a=.$length, b=.$value)) %>% 
  group_by(b) %>% 
  mutate(n = 1:n()) %>%
  with(., rep(n, times=a)) %>% 
  bind_cols(dummy_df, res=.)
   s desired_output res
1  a              1   1
2  a              1   1
3  b              1   1
4  b              1   1
5  b              1   1
6  c              1   1
7  c              1   1
8  a              2   2
9  a              2   2
10 c              2   2
11 c              2   2
12 a              3   3
13 a              3   3