Новый вектор с буквами, представляющими уникальные комбинации других векторов - PullRequest
0 голосов
/ 08 июня 2018

У меня

dat <-data.frame(study=letters[c(1,1,1,4,4,4,4,10,10)],n1i=c(25,25,22,38,50,30,30,50,50)) 

Я хочу

     study n1i grp
1     a  25   A
2     a  25   A
3     a  22   B
4     d  38   A
5     d  50   B
6     d  30   C
7     d  30   C
8     j  50   A
9     j  50   A

Но это ...

dat$grp<-  
  as.vector(unlist(aggregate(dat$n1i,
   list(dat$study), function(x) LETTERS[1:length(x)])$x)) 

... дает мне

> dat
  study n1i grp
1     a  25   A
2     a  25   B
3     a  22   C
4     d  38   A
5     d  50   B
6     d  30   C
7     d  30   D
8     j  50   A
9     j  50   B

Словами, я хочу, чтобы буквы "grp" переходили от 1 до всякий раз, когда они достигают последней уникальной комбинации обучения * n1i.

Ответы [ 5 ]

0 голосов
/ 11 июня 2018

С tidyverse, используя dplyr::group_indices:

dat %>%
  split(.$study) %>%
  map_dfr(~mutate(.,id = LETTERS[
    group_indices(.,factor(n1i,unique(n1i)))]))

#   study n1i id
# 1     a  25  A
# 2     a  25  A
# 3     a  22  B
# 4     d  38  A
# 5     d  50  B
# 6     d  30  C
# 7     d  30  C
# 8     j  50  A
# 9     j  50  A
0 голосов
/ 08 июня 2018

Или другой вариант: data.table

library(data.table)
setDT(dat)[, grp := LETTERS[rleid(n1i)], study]
dat
#   study n1i grp
#1:     a  25   A
#2:     a  25   A
#3:     a  22   B
#4:     d  38   A
#5:     d  50   B
#6:     d  30   C
#7:     d  30   C
#8:     j  50   A
#9:     j  50   A

РЕДАКТИРОВАТЬ

Исходя из комментария @ AntoniosK, правильный вывод должен быть

setDT(dat)[, i1 := seq_len(.N), study][, grp := LETTERS[min(i1)], 
                .(study, n1i)][, i1 := NULL][]
#   study n1i grp
#1:     a  25   A
#2:     a  25   A
#3:     a  22   C
#4:     d  38   A
#5:     d  50   B
#6:     d  30   C
#7:     d  30   C
#8:     j  50   A
#9:     j  50   A
0 голосов
/ 08 июня 2018

Это основано на идентификаторе кодирования длины серии, который предполагает, что уникальные комбинации появляются только в чанках, а не в отдельных строках.

library(dplyr)
library(data.table)

dat2 <- dat %>%
  group_by(study) %>%
  mutate(grp =rleid(n1i)) %>%
  mutate(grp = LETTERS[grp]) %>%
  ungroup()
dat2
# # A tibble: 9 x 3
#   study   n1i grp  
#   <fct> <dbl> <chr>
# 1 a        25 A    
# 2 a        25 A    
# 3 a        22 B    
# 4 d        38 A    
# 5 d        50 B    
# 6 d        30 C    
# 7 d        30 C    
# 8 j        50 A    
# 9 j        50 A 

Это решение может быть не идеальным.Например, если фрейм данных выглядит следующим образом:

study   n1i
   a     25
   a     22
   a     25

Кодировка длины прогона станет 1, 2, 3.В этом случае вы можете сначала заказать свой фрейм данных, чтобы создать одну и ту же строку в одном и том же фрагменте.Я не разместил заказ или не организовал вызов в своем решении, потому что я не знаю, нужно ли переупорядочивать строки.

ОБНОВЛЕНИЕ

АнтониосК прокомментировал, что первыйтри строки должны быть A, A, C.Я добавил min_rank к операции pipe, чтобы учесть это утверждение.

dat2 <- dat %>%
  group_by(study) %>%
  mutate(grp =rleid(n1i)) %>%
  mutate(grp = min_rank(grp)) %>%
  mutate(grp = LETTERS[grp]) %>%
  ungroup()
dat2
# # A tibble: 9 x 3
#   study   n1i grp  
#   <fct> <dbl> <chr>
# 1 a        25 A    
# 2 a        25 A    
# 3 a        22 C    
# 4 d        38 A    
# 5 d        50 B    
# 6 d        30 C    
# 7 d        30 C    
# 8 j        50 A    
# 9 j        50 A 
0 голосов
/ 08 июня 2018

Вот один вкладыш без дополнительных пакетов,

LETTERS[with(dat, ave(n1i, study, FUN = function(i) 
                                cumsum(!duplicated(i) | duplicated(i, fromLast = TRUE))))]
#[1] "A" "A" "B" "A" "B" "C" "C" "A" "A"
0 голосов
/ 08 июня 2018
dat <-data.frame(study=letters[c(1,1,1,4,4,4,4,10,10)],n1i=c(25,25,22,38,50,30,30,50,50)) 

library(dplyr)

dat %>%
  group_by(study) %>%                    # for each study
  mutate(id = row_number()) %>%          # get the number of row as an id
  group_by(study, n1i) %>%               # for each study and n1i combination
  transmute(grp = LETTERS[min(id)]) %>%  # add the letters based on the minimum id value of that combination, while removing the id column
  ungroup()                              # forget the grouping

# # A tibble: 9 x 3
#   study   n1i grp  
#   <fct> <dbl> <chr>
# 1 a        25 A    
# 2 a        25 A    
# 3 a        22 C    
# 4 d        38 A    
# 5 d        50 B    
# 6 d        30 C    
# 7 d        30 C    
# 8 j        50 A    
# 9 j        50 A 

Этот подход предполагает, что дублирующиеся строки располагаются одна за другой.

...