如何在 R 中使用 dplyr 运行 高效 group_by 语句

How to run efficient group_by statement using dplyr in R

我有一个包含多个重复 ID 的数据集,这些 ID 具有不同的分类值。以下是示例数据集。

suppressMessages(library(dplyr))
DUMMY_DATA <- data.frame(ID = c(11,22,22,33,33,33,44,44,55,55,55,55),
                     CATEGORY1 = c("E","B","C","C","C","D","A","A","B","C","E","B"),
                     CATEGORY2 = c ("AA","AA","BB","CC","DD","BB","AA","EE","AA","CC","BB","EE"),
                     stringsAsFactors = FALSE)

> DUMMY_DATA
   ID CATEGORY1 CATEGORY2
1  11         E        AA
2  22         B        AA
3  22         C        BB
4  33         C        CC
5  33         C        DD
6  33         D        BB
7  44         A        AA
8  44         A        EE
9  55         B        AA
10 55         C        CC
11 55         E        BB
12 55         B        EE

我想聚合另一个数据集中的 ID 值,该数据集给出了分类值的排名。如下

Category_Rank1 <- data.frame(VAR = c("A","B","C","D","E"),
                        RANK = c(1,2,3,4,5),stringsAsFactors = FALSE
)
> Category_Rank1
  VAR RANK
1   A    1
2   B    2
3   C    3
4   D    4
5   E    5

Category_Rank2 <- data.frame(VAR = c("AA","BB","CC","DD","EE"),
                            RANK = c(1,2,3,4,5),stringsAsFactors = FALSE
)

> Category_Rank2
  VAR RANK
1  AA    1
2  BB    2
3  CC    3
4  DD    4
5  EE    5

对于来自 DUMMY_DAT 的每组 ID,我想查找 Category_Rank,然后将该类别分配给排名最高的 ID。以下是我的解决方案。

hierarchyTransform <- function(x,dataset){
  x <- unique(x)
  dataset <- dataset%>%
    filter(dataset[,1] %in% x)
  dataset <- dataset%>%
    filter(dataset[,2] == min(dataset[,2]))
  return(dataset[1,1])
}


NEW_DATA <- DUMMY_DATA%>%
          group_by(ID)%>%
          summarise(CATEGORY1_CLEAN = hierarchyTransform(x=CATEGORY1,
                                                         dataset = Category_Rank1),
                    CATEGORY2_CLEAN = hierarchyTransform(x=CATEGORY2,
                                                         dataset = Category_Rank2))

我得到以下结果。

> NEW_DATA
# A tibble: 5 × 3
     ID CATEGORY1_CLEAN CATEGORY2_CLEAN
   <dbl>           <chr>           <chr>
1    11               E              AA
2    22               B              AA
3    33               C              BB
4    44               A              AA
5    55               B              AA

这正是我想要的,但问题是此操作花费的时间。我的原始数据集有大约 100 万行,当我根据 ID 对其进行分组时,我得到大约 200,000 个组。因此,hierarchyTransform 函数应用于 200,000 个组,单个变量大约需要 15 分钟,我必须对其他 10 个变量执行此操作,这会增加时间。有什么办法可以减少这个操作的时间吗

如果您知道 CATEGORY 级别的排名顺序(在您的示例中是按字母顺序排列的),那么您可以将 CATEGORY 转换为一个根据所需排名对级别进行排序的因子。然后按 CATEGORY 排序,按 ID 分组,每个 ID.

取第一行
DUMMY_DATA$CATEGORY = factor(DUMMY_DATA$CATEGORY, levels=LETTERS[1:5], ordered=TRUE)

DUMMY_DATA %>% 
  arrange(ID, CATEGORY) %>%
  group_by(ID) %>%
  slice(1)
     ID CATEGORY
1    11        E
2    22        B
3    33        C
4    44        A
5    55        B

更新: 回复您的评论和更新的问题:下面的代码将为每个 ID、select 的最高排名值每个类别列。

DUMMY_DATA$CATEGORY1 = factor(DUMMY_DATA$CATEGORY1, levels=LETTERS[1:5], ordered=TRUE)
DUMMY_DATA$CATEGORY2 = factor(DUMMY_DATA$CATEGORY2, levels=c("AA","BB","CC","DD","EE"), ordered=TRUE)

现在您可以执行以下任一操作:

DUMMY_DATA %>% group_by(ID) %>%
  summarise(CATEGORY1 = min(CATEGORY1),
            CATEGORY2 = min(CATEGORY2))

DUMMY_DATA %>% group_by(ID) %>%
  summarise_all(funs(min))
     ID CATEGORY1 CATEGORY2
1    11         E        AA
2    22         B        AA
3    33         C        BB
4    44         A        AA
5    55         B        AA