Подтвердить что ты не робот

Как добавить количество уникальных значений по группам в R data.frame

Я хочу подсчитать количество уникальных значений, группируя вторую переменную, а затем добавьте счет в существующий data.frame в качестве нового столбца. Например, если существующий фрейм данных выглядит следующим образом:

  color  type
1 black chair
2 black chair
3 black  sofa
4 green  sofa
5 green  sofa
6   red  sofa
7   red plate
8  blue  sofa
9  blue plate
10 blue chair

Я хочу добавить для каждого color количество уникальных types, которые присутствуют в данных:

  color  type unique_types
1 black chair            2
2 black chair            2
3 black  sofa            2
4 green  sofa            1
5 green  sofa            1
6   red  sofa            2
7   red plate            2
8  blue  sofa            3
9  blue plate            3
10 blue chair            3

Я надеялся использовать ave, но не могу найти простой метод, который не требует много строк. У меня есть > 100 000 строк, поэтому я также не уверен, насколько важна эффективность.

Это несколько похоже на эту проблему: Подсчитайте количество наблюдений/строк на группу и добавьте результат в кадр данных

4b9b3361

Ответ 1

Используя ave (поскольку вы запрашиваете его конкретно):

within(df, { count <- ave(type, color, FUN=function(x) length(unique(x)))})

Убедитесь, что type является символьным вектором, а не фактором.


Поскольку вы также говорите, что ваши данные огромны, и поэтому скорость и производительность могут быть фактором, я бы предложил также решение data.table.

require(data.table)
setDT(df)[, count := uniqueN(type), by = color] # v1.9.6+
# if you don't want df to be modified by reference
ans = as.data.table(df)[, count := uniqueN(type), by = color]

uniqueN был реализован в v1.9.6 и является более быстрым эквивалентом length(unique(.)). Кроме того, он также работает с data.frames/data.tables.


Другие решения:

Использование plyr:

require(plyr)
ddply(df, .(color), mutate, count = length(unique(type)))

Используя aggregate:

agg <- aggregate(data=df, type ~ color, function(x) length(unique(x)))
merge(df, agg, by="color", all=TRUE)

Ответ 2

Здесь решение с пакетом dplyr - оно имеет n_distinct() в качестве обертки для length(unique()).

df %>%
  group_by(color) %>%
  mutate(unique_types = n_distinct(type))

Ответ 3

Это также может быть достигнуто в векторизации без групповых операций путем объединения unique с table или tabulate

Если df$color - factor, то

Либо

table(unique(df)$color)[as.character(df$color)]
# black black black green green   red   red  blue  blue  blue 
#    2     2     2     1     1     2     2     3     3     3 

Или

tabulate(unique(df)$color)[as.integer(df$color)]
# [1] 2 2 2 1 1 2 2 3 3 3

Если df$color - character, тогда просто

table(unique(df)$color)[df$color]

Если df$color является integer, тогда просто

tabulate(unique(df)$color)[df$color]