#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