按组将唯一/不同值的计数添加到原始数据

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】:

这也可以通过将uniquetabletabulate 组合在向量化的情况下实现,而无需分组操作

如果df$colorfactor,那么

要么

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$colorcharacter 那么就

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

如果df$colorinteger,那么只需

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

【讨论】:

以上是关于按组将唯一/不同值的计数添加到原始数据的主要内容,如果未能解决你的问题,请参考以下文章

按组将一列转换为多列

按组将数据框日期拆分为单个最小最大日期范围

按组将函数应用于整个数据表

重塑数据框以按组将值设为列[重复]

两个不同对象数组中唯一值的计数

在 R 中按组将数据从 Long 重塑为 Wide