You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将dplyr的group_by/mutate/filter/pivot_wider转为data.table实现?

使用data.table替代dplyr实现高效数据处理

我有如下数据框:

dat <- structure(list(ref_string = c("K", "Y", "Q", "C", "H", "A", "S", 
"Y", "L", "Y"), peptide_name = c("p47", "p666", "p506", "p356", 
"p598", "p458", "p448", "p117", "p232", "p464"), peptide = c("FKDHKHIDVKgrrrskrrrrTRCYHIDPHH", 
"FKDHKHIDVKsrgrkrrrrrTRCYHIDPHH", "FKDHKHIDVKrrrrskrgrrTRCYHIDPHH", 
"FKDHKHIDVKrrrgrrrrskTRCYHIDPHH", "FKDHKHIDVKrsgrrrrrkrTRCYHIDPHH", 
"FKDHKHIDVKrrrrrkrrgsTRCYHIDPHH", "FKDHKHIDVKrrrrrgrskrTRCYHIDPHH", 
"FKDHKHIDVKkrrrrsrrgrTRCYHIDPHH", "FKDHKHIDVKrkrrrrsgrrTRCYHIDPHH", 
"FKDHKHIDVKrrrrrksrrgTRCYHIDPHH"), status = c(0, 0, 0, 0, 0, 
0, 0, 0, 0, 0)), class = c("rowwise_df", "tbl_df", "tbl", "data.frame"
), row.names = c(NA, -10L), groups = structure(list(.rows = structure(list(
    1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), ptype = integer(0), class = c("vctrs_list_of", 
"vctrs_vctr", "list"))), row.names = c(NA, -10L), class = c("tbl_df", 
"tbl", "data.frame")))

对应的表格展示:

# A tibble: 10 × 4
# Rowwise: 
   ref_string peptide_name peptide                        status
   <chr>      <chr>        <chr>                           <dbl>
 1 K          p47          FKDHKHIDVKgrrrskrrrrTRCYHIDPHH      0
 2 Y          p666         FKDHKHIDVKsrgrkrrrrrTRCYHIDPHH      0
 3 Q          p506         FKDHKHIDVKrrrrskrgrrTRCYHIDPHH      0
 4 C          p356         FKDHKHIDVKrrrgrrrrskTRCYHIDPHH      0
 5 H          p598         FKDHKHIDVKrsgrrrrrkrTRCYHIDPHH      0
 6 A          p458         FKDHKHIDVKrrrrrkrrgsTRCYHIDPHH      0
 7 S          p448         FKDHKHIDVKrrrrrgrskrTRCYHIDPHH      0
 8 Y          p117         FKDHKHIDVKkrrrrsrrgrTRCYHIDPHH      0
 9 L          p232         FKDHKHIDVKrkrrrrsgrrTRCYHIDPHH      0
10 Y          p464         FKDHKHIDVKrrrrrksrrgTRCYHIDPHH      0

原本使用dplyr的处理代码,但在大数据集上运行缓慢:

library(tidyverse)
dat %>% 
  dplyr::group_by(peptide_name, peptide) %>% 
  mutate(tot = sum(status)) %>% 
  filter(tot == 0) %>%  
  pivot_wider(names_from = ref_string, values_from = status) %>%
  dplyr::select(-tot) %>% 
  ungroup()

输出结果:

# A tibble: 10 × 10
   peptide_name peptide                            K     Y     Q     C     H     A     S     L
   <chr>        <chr>                          <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1 p47          FKDHKHIDVKgrrrskrrrrTRCYHIDPHH     0    NA    NA    NA    NA    NA    NA    NA
 2 p666         FKDHKHIDVKsrgrkrrrrrTRCYHIDPHH    NA     0    NA    NA    NA    NA    NA    NA
 3 p506         FKDHKHIDVKrrrrskrgrrTRCYHIDPHH    NA    NA     0    NA    NA    NA    NA    NA
 4 p356         FKDHKHIDVKrrrgrrrrskTRCYHIDPHH    NA    NA    NA     0    NA    NA    NA    NA
 5 p598         FKDHKHIDVKrsgrrrrrkrTRCYHIDPHH    NA    NA    NA    NA     0    NA    NA    NA
 6 p458         FKDHKHIDVKrrrrrkrrgsTRCYHIDPHH    NA    NA    NA    NA    NA     0    NA    NA
 7 p448         FKDHKHIDVKrrrrrgrskrTRCYHIDPHH    NA    NA    NA    NA    NA    NA     0    NA
 8 p117         FKDHKHIDVKkrrrrsrrgrTRCYHIDPHH    NA     0    NA    NA    NA    NA    NA    NA
 9 p232         FKDHKHIDVKrkrrrrsgrrTRCYHIDPHH    NA    NA    NA    NA    NA    NA    NA     0
10 p464         FKDHKHIDVKrrrrrksrrgTRCYHIDPHH    NA     0    NA    NA    NA    NA    NA    NA

data.table实现方案

完整代码

library(data.table)

# 转换为data.table格式
dt <- as.data.table(dat)

# 1. 分组计算status的总和,按peptide_name和peptide分组
dt[, tot := sum(status), by = .(peptide_name, peptide)]

# 2. 过滤出tot等于0的行
dt_filtered <- dt[tot == 0]

# 3. 使用dcast实现宽表转换,对应dplyr的pivot_wider
result <- dcast(dt_filtered, peptide_name + peptide ~ ref_string, value.var = "status")

# 4. 删除tot列
result[, tot := NULL]

# 查看最终结果
result

运行结果

peptide_name                        peptide  K  Y  Q  C  H  A  S  L
 1:          p47 FKDHKHIDVKgrrrskrrrrTRCYHIDPHH  0 NA NA NA NA NA NA NA
 2:         p666 FKDHKHIDVKsrgrkrrrrrTRCYHIDPHH NA  0 NA NA NA NA NA NA
 3:         p506 FKDHKHIDVKrrrrskrgrrTRCYHIDPHH NA NA  0 NA NA NA NA NA
 4:         p356 FKDHKHIDVKrrrgrrrrskTRCYHIDPHH NA NA NA  0 NA NA NA NA
 5:         p598 FKDHKHIDVKrsgrrrrrkrTRCYHIDPHH NA NA NA NA  0 NA NA NA
 6:         p458 FKDHKHIDVKrrrrrkrrgsTRCYHIDPHH NA NA NA NA NA  0 NA NA
 7:         p448 FKDHKHIDVKrrrrrgrskrTRCYHIDPHH NA NA NA NA NA NA  0 NA
 8:         p117 FKDHKHIDVKkrrrrsrrgrTRCYHIDPHH NA  0 NA NA NA NA NA NA
 9:         p232 FKDHKHIDVKrkrrrrsgrrTRCYHIDPHH NA NA NA NA NA NA NA  0
10:         p464 FKDHKHIDVKrrrrrksrrgTRCYHIDPHH NA  0 NA NA NA NA NA NA

关键步骤解析

  • 分组求和:data.table采用[, 新列 := 计算逻辑, by = .(分组列)]的语法,这里必须和dplyr保持一致,按peptide_name和peptide双列分组
  • 行过滤:直接用dt[过滤条件]即可实现dplyr中filter的功能,语法更简洁
  • 宽表转换:使用dcast函数,格式为dcast(数据集, 标识列 ~ 列名来源列, value.var = 取值列),完美对应pivot_wider的功能
  • 列删除:用[, 列名 := NULL]可以快速删除指定列,无需额外函数

大数据集优化

如果处理超大规模数据,可以将步骤合并为链式操作,减少中间数据对象的创建,进一步提升效率:

result <- dt[, tot := sum(status), by = .(peptide_name, peptide)
             ][tot == 0
               ][, dcast(.SD, peptide_name + peptide ~ ref_string, value.var = "status")
                 ][, tot := NULL]

内容的提问来源于stack exchange,提问作者littleworth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 07:20:35