Порядковый номер для повторяющихся строк в r

#r #dplyr #lapply

Вопрос:

У меня есть фрейм данных с числовыми и символьными столбцами, в которых некоторые строки дублируются. Чтобы выделить эти строки, я хочу добавить в каждый «блок» повторяющихся строк порядковый номер от 1:n в качестве нового столбца (в моем примере он называется «duplicateID»).

Мой набор данных выглядит следующим образом:

 a = c("one", "one", "one", "one", "two", "two", "three", "four", "four", "four")
b = c(3.5, 3.5, 3.5, 2.5, 3.5, 3.5, 1, 2.2, 7, 7)
df1 <-data.frame(a,b)

>df1
       a   b
1    one 3.5
2    one 3.5
3    one 3.5
4    one 2.5
5    two 3.5
6    two 3.5
7  three 1.0
8   four 2.2
9   four 7.0
10  four 7.0
 

Желаемый результат -:

 a = c("one", "one", "one", "one", "two", "two", "three", "four", "four", "four")
b = c(3.5, 3.5, 3.5, 2.5, 3.5, 3.5, 1, 2.2, 7, 7)
duplicateID = c(1, 2, 3, 1, 1, 2, 1, 1, 1, 2)
df2 <-data.frame(a,b,duplicateID)

>df2 
       a   b duplicateID
1    one 3.5           1
2    one 3.5           2
3    one 3.5           3
4    one 2.5           1
5    two 3.5           1
6    two 3.5           2
7  three 1.0           1
8   four 2.2           1
9   four 7.0           1
10  four 7.0           2
 

Заранее всем вам спасибо!

Ответ №1:

Один из способов достичь этого с помощью dplyr :

 library(dplyr)

df1 %>% 
    # build grouping by combination of variables
    dplyr::group_by(a, b) %>%
    # add row number which works per group due to prior grouping
    dplyr::mutate(duplicateID = dplyr::row_number()) %>%
    # ungroup to prevent unexpected behaviour down stream
    dplyr::ungroup()

# A tibble: 10 x 3
   a         b  duplicateID
   <chr> <dbl>     <int>
 1 one     3.5       1
 2 one     3.5       2
 3 one     3.5       3
 4 one     2.5       1
 5 two     3.5       1
 6 two     3.5       2
 7 three   1         1
 8 four    2.2       1
 9 four    7         1
10 four    7         2
 

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

1. Спасибо вам за это простое решение! Приятно знать, что это возможно с dplyr!

2. Так же, как информация: мы могли бы использовать across в этой настройке: library(dplyr) df1 %>% group_by(across()) %>% mutate(duplicatedID = row_number())

Ответ №2:

Возможно, это будет не так быстро, как dplyr (конечно, в data.table тоже есть опции), но в базе R вы можете добиться этого с помощью функции «ave» с «seq_along».:

 a = c("one", "one", "one", "one", "two", "two", "three", "four", "four", "four")
b = c(3.5, 3.5, 3.5, 2.5, 3.5, 3.5, 1, 2.2, 7, 7)
df1 <-data.frame(a,b)
df1$dupID = NA
df1$dupID = with(df1,ave(dupID,b,a,FUN = seq_along))
 

Ответ №3:

Мы могли бы использовать rowid

 library(data.table)
setDT(df1)[, dupID := rowid(a, b)]
 

-выход

 > df1
        a   b dupID
 1:   one 3.5     1
 2:   one 3.5     2
 3:   one 3.5     3
 4:   one 2.5     1
 5:   two 3.5     1
 6:   two 3.5     2
 7: three 1.0     1
 8:  four 2.2     1
 9:  four 7.0     1
10:  four 7.0     2