Как добавить количество уникальных значений по группам в 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 строк, поэтому я также не уверен, насколько важна эффективность.
Это несколько похоже на эту проблему: Подсчитайте количество наблюдений/строк на группу и добавьте результат в кадр данных
Ответы
Ответ 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]