Как преобразовать group_by, mutate, filter, pivot_wider dplyr в подход data.table

У меня есть следующий фрейм данных:

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)
dt <- as.data.table(dat)
dt[,by = peptide, tot:=sum(status) ]
dt

С этим результатом:

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

Я не знаю, как использовать filter и pivot_wider для data.table.

Где вы застряли, когда пытались написать код data.table?

user438383 11.11.2022 10:20
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения &quot;многие ко многим&quot; в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
1
1
67
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Попробуйте dtplyr, который позволяет использовать команды dplyr и tidyr с data.table в качестве бэкенда:

library(dplyr)
library(tidyr)
library(dtplyr)

dat_dt <- lazy_dt(dat)

dat_dt %>% 
  group_by(peptide_name, peptide) %>% 
  mutate(tot = sum(status)) %>% 
  filter(tot == 0) %>%  
  pivot_wider(names_from = ref_string, values_from = status) %>%
  select(-tot) %>% 
  ungroup() %>%
  as_tibble()
# 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 p117         FKDHKHIDVKkrrrr…    NA     0    NA    NA    NA    NA    NA    NA
 2 p232         FKDHKHIDVKrkrrr…    NA    NA    NA    NA    NA    NA    NA     0
 3 p356         FKDHKHIDVKrrrgr…    NA    NA    NA     0    NA    NA    NA    NA
 4 p448         FKDHKHIDVKrrrrr…    NA    NA    NA    NA    NA    NA     0    NA
 5 p458         FKDHKHIDVKrrrrr…    NA    NA    NA    NA    NA     0    NA    NA
 6 p464         FKDHKHIDVKrrrrr…    NA     0    NA    NA    NA    NA    NA    NA
 7 p47          FKDHKHIDVKgrrrs…     0    NA    NA    NA    NA    NA    NA    NA
 8 p506         FKDHKHIDVKrrrrs…    NA    NA     0    NA    NA    NA    NA    NA
 9 p598         FKDHKHIDVKrsgrr…    NA    NA    NA    NA     0    NA    NA    NA
10 p666         FKDHKHIDVKsrgrk…    NA     0    NA    NA    NA    NA    NA    NA

Микробенчмарк:

Unit: milliseconds
   expr      min       lq     mean   median       uq      max neval cld
  dplyr 27.80141 29.91216 32.92722 31.35731 33.91613 73.43162   100   b
 dtplyr 18.60528 20.17416 22.33375 21.38543 23.15164 52.08883   100  a 

Интересный момент с dtplyr заключается в том, что если вы используете show_query() вместо as_tibble(), вы получите близкий к data.table синтаксис решения.

Waldi 11.11.2022 11:08
Ответ принят как подходящий

Вот вариант data.table, где dcast следует использовать для поворота шире.

dcast(
  setDT(dat)[
    ,
    tot := sum(status),
    .(peptide_name, peptide)
  ][tot == 0],
  peptide_name + peptide ~ ref_string,
  value.var = "status"
)

И вы увидите результат как

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

Еще один способ решить вашу проблему с помощью data.table

dcast(data = setDT(dat)[, if (sum(status)==0) .SD, by=.(peptide_name, peptide)],
      formula = peptide_name + peptide ~ ref_string, 
      value.var = "status")

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

Другие вопросы по теме