按组将唯一/不同值的计数添加到原始数据
Posted
技术标签:
【中文标题】按组将唯一/不同值的计数添加到原始数据【英文标题】:Add count of unique / distinct values by group to the original data 【发布时间】:2013-06-29 14:17:45 【问题描述】:我希望通过对第二个变量进行分组来计算唯一值的数量,然后将该计数作为新列添加到现有的 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 行,所以我也不确定效率有多重要。
有点类似这个问题:Count number of observations/rows per group and add result to data frame
【问题讨论】:
【参考方案1】:这是一个使用 dplyr 包的解决方案 - 它具有 n_distinct()
作为 length(unique())
的包装器。
df %>%
group_by(color) %>%
mutate(unique_types = n_distinct(type))
【讨论】:
感谢山姆的 dplyr 解决方案。假设我想更进一步,“子集” df 仅包含“颜色”和“不同类型的相应数量”。我记得这些有一个巧妙的功能,但我不记得了,建议?【参考方案2】:使用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)
【讨论】:
如果您没有 NA 值,则在plyr
版本中使用 length(unique(type))
仅等效于 data.table::uniqueN(type)
。 uniqueN
将为空组报告 0,而 length(unique(type))
将报告 1! dplyr
(不确定plyr
)等价于data.table::uniqueN(x, na.rm = TRUE)
是dplyr::n_distinct(x, na.rm = TRUE)
【参考方案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]
【讨论】:
以上是关于按组将唯一/不同值的计数添加到原始数据的主要内容,如果未能解决你的问题,请参考以下文章