在数据框中过滤出前n个最大的分组

8

针对示例数据:

set.seed(2222)
example_data <- data.frame(col1 = 1:15,
                           col2 = 16:30, 
                           group = sample(1:3, 15, replace = TRUE))

   col1 col2 group
1     1   16     2
2     2   17     1
3     3   18     3
4     4   19     2
5     5   20     3
6     6   21     1
7     7   22     3
8     8   23     1
9     9   24     3
10   10   25     1
11   11   26     2
12   12   27     2
13   13   28     2
14   14   29     3
15   15   30     3

我希望找到记录数量最多的前n个组。

假设我想获取记录数量最多的前2个组。在数据中,这将是第3组和第2组:

example_data %>% 
  group_by(group) %>% 
  summarise(n = n())

# A tibble: 3 x 2
  group     n
  <int> <int>
1     1     4
2     2     5
3     3     6

预期的输出为:
   col1 col2 group
1     1   16     2
2     3   18     3
3     4   19     2
4     5   20     3
5     7   22     3
6     9   24     3
7    11   26     2
8    12   27     2
9    13   28     2
10   14   29     3
11   15   30     3

这里有非常相似的问题,其答案也非常相似:这里这里 - camille
类似但不同的是,一个是在组内查找前n个,另一个是过滤固定大小的组。 - clemens
5个回答

5
我们可以使用 table 来计算每个 group 的频率,用 decreasing 的方式对它们进行 sort,然后子集选择前两个数据,并对应筛选相应的组。
library(dplyr)

example_data %>%
   filter(group %in% names(sort(table(group), decreasing = TRUE)[1:2]))


#   col1 col2 group
#1     1   16     2
#2     3   18     3
#3     4   19     2
#4     5   20     3
#5     7   22     3
#6     9   24     3
#7    11   26     2
#8    12   27     2
#9    13   28     2
#10   14   29     3
#11   15   30     3

您也可以直接在基础 R 中使用 subset 方法。

subset(example_data, group %in% names(sort(table(group), decreasing = TRUE)[1:2]))

3
我们可以使用tidyverse方法来完成这个任务。使用add_count创建一个频率列,按照该列使用arrange,并使用filter过滤行,其中'group'在最后两个unique'group'值中。
library(dplyr)
example_data %>% 
   add_count(group) %>% 
   arrange(n) %>%
   filter(group %in% tail(unique(group), 2)) %>%
   select(-n)
# A tibble: 11 x 3
#    col1  col2 group
#  <int> <int> <int>
# 1     1    16     2
# 2     4    19     2
# 3    11    26     2
# 4    12    27     2
# 5    13    28     2
# 6     3    18     3
# 7     5    20     3
# 8     7    22     3
# 9     9    24     3
#10    14    29     3
#11    15    30     3

或者使用 data.table
library(data.table)
setDT(example_data)[group %in% example_data[, .N, group][order(-N), head(group, 2)]]

3

使用dplyr,你也可以进行以下操作:

example_data %>%
 add_count(group) %>%
 filter(dense_rank(desc(n)) <= 2) %>%
 select(-n)

   col1  col2 group
   <int> <int> <int>
 1     1    16     2
 2     3    18     3
 3     4    19     2
 4     5    20     3
 5     7    22     3
 6     9    24     3
 7    11    26     2
 8    12    27     2
 9    13    28     2
10    14    29     3
11    15    30     3

或者:

example_data %>%
 add_count(group) %>%
 slice(which(dense_rank(desc(n)) <= 2)) %>%
 select(-n)

2

另一种使用dplyr的方法可能是:

最初的回答:

example_data %>% 
  group_by(group) %>% 
  count() %>% 
  ungroup() %>% 
  top_n(n = 2, wt = n) %>% 
  select(-n) %>% 
  inner_join(example_data)

0

另一个解决方案(类似于@OTStats):

library(dplyr)

example_data %>% 
  inner_join(
    count(., group) %>% top_n(2, n) %>% dplyr::select(group)
    )

#    col1 col2 group
# 1     1   16     2
# 2     3   18     3
# 3     4   19     2
# 4     5   20     3
# 5     7   22     3
# 6     9   24     3
# 7    11   26     2
# 8    12   27     2
# 9    13   28     2
# 10   14   29     3
# 11   15   30     3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接