использование оператора %>% из dplyr в R

#r #dplyr #tidyverse

Вопрос:

Я видел примеры кода, использующего оператор %>% из пакета dplyr (или tidyverse) в R для выполнения последовательности действий над одним и тем же объектом или фреймом данных. Однако мне никогда не удавалось заставить это работать для моего собственного кода. Например, в приведенном ниже коде я пытаюсь заменить часть «1:2=» каждой ячейки в столбце, а затем преобразовать столбец в числовой. Это прекрасно работает, если я выполняю каждый шаг по одному за раз, но приводит к ошибке, когда я пытаюсь передать одну команду следующей.

Кто-нибудь может помочь мне понять, что я здесь делаю не так?

 > df <- as.data.frame(vroom("manhattan_practice_data.txt", col_names = c("chromosome", "position", "num_SNPs", "prop_SNPs_coverage", "min_coverage", "AvsDD", "AvsWD", "DDvsWD")))
Rows: 79 Columns: 8                                                                                                                                           
-- Column specification ---------------------------------------------------------------------------------------------------
Delimiter: " "
chr (4): chromosome, AvsDD, AvsWD, DDvsWD
dbl (4): position, num_SNPs, prop_SNPs_coverage, min_coverage

i Use `spec()` to retrieve the full column specification for this data.
i Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(df)
'data.frame':   79 obs. of  8 variables:
 $ chromosome        : chr  "A01" "A01" "A01" "A01" ...
 $ position          : num  139 149 384 544 547 552 558 615 686 693 ...
 $ num_SNPs          : num  1 1 1 1 1 1 1 1 1 1 ...
 $ prop_SNPs_coverage: num  1 1 1 1 1 1 1 1 1 1 ...
 $ min_coverage      : num  104 32 79 46 48 52 60 30 98 94 ...
 $ AvsDD             : chr  "1:2=0.00000000" "1:2=0.08624012" "1:2=0.13233606" "1:2=0.00000000" ...
 $ AvsWD             : chr  "1:3=0.10843987" "1:3=0.00000000" "1:3=0.12724615" "1:3=0.23923465" ...
 $ DDvsWD            : chr  "2:3=0.33696506" "2:3=0.38416539" "2:3=0.00000000" "2:3=0.26549660" ...
 - attr(*, "spec")=
  .. cols(
  ..   chromosome = col_character(),
  ..   position = col_double(),
  ..   num_SNPs = col_double(),
  ..   prop_SNPs_coverage = col_double(),
  ..   min_coverage = col_double(),
  ..   AvsDD = col_character(),
  ..   AvsWD = col_character(),
  ..   DDvsWD = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

> df <- df %>% gsub("1:2=","",as.character(AvsDD)) %>% as.numeric(AvsDD)
Error in gsub("1:2=", "", as.character(AvsDD)) : object 'AvsDD' not found
 

Однако это прекрасно работает, когда я выполняю каждый шаг по одному за раз, и в результате столбец AvsDD преобразуется в числовой:

 > df$AvsDD <- gsub("1:2=","",as.character(df$AvsDD))
> df$AvsDD <- as.numeric(df$AvsDD)
> str(df)
'data.frame':   79 obs. of  8 variables:
 $ chromosome        : chr  "A01" "A01" "A01" "A01" ...
 $ position          : num  139 149 384 544 547 552 558 615 686 693 ...
 $ num_SNPs          : num  1 1 1 1 1 1 1 1 1 1 ...
 $ prop_SNPs_coverage: num  1 1 1 1 1 1 1 1 1 1 ...
 $ min_coverage      : num  104 32 79 46 48 52 60 30 98 94 ...
 $ AvsDD             : num  0 0.0862 0.1323 0 0 ...
 $ AvsWD             : chr  "1:3=0.10843987" "1:3=0.00000000" "1:3=0.12724615" "1:3=0.23923465" ...
 $ DDvsWD            : chr  "2:3=0.33696506" "2:3=0.38416539" "2:3=0.00000000" "2:3=0.26549660" ...
 - attr(*, "spec")=
  .. cols(
  ..   chromosome = col_character(),
  ..   position = col_double(),
  ..   num_SNPs = col_double(),
  ..   prop_SNPs_coverage = col_double(),
  ..   min_coverage = col_double(),
  ..   AvsDD = col_character(),
  ..   AvsWD = col_character(),
  ..   DDvsWD = col_character()
  .. )
 - attr(*, "problems")=<externalptr>
 

Комментарии:

1. df %>% gsub("1:2=","",as.character(AvsDD)) : %>% В этом случае канал всегда использует левую сторону (LHS) и в этом случае df передает в качестве первого аргумента функцию с правой стороны (RHS) gsub . Таким образом, ваш код эквивалентен gsub(df, "1:2=","",as.character(AvsDD)) тому, который нарушает gsub синтаксис. Поскольку «старые» функции, такие как gsub , используют какой-то странный порядок аргументации, существует несколько новых пакетов, совместимых с каналом. Для строковых операций, на которые вы могли бы взглянуть stringr .

Ответ №1:

При dplyr этом операции преобразования выполняются в mutate

 library(dplyr)
df <- df %>% 
    mutate(AvsDD = as.numeric(gsub("1:2=","",as.character(AvsDD), fixed = TRUE))) 
 

Хотя, можно выполнять операции, которые выполнял OP, извлекая столбец ( .$ ) и оборачивая, {} но это не очень хороший подход


Поскольку существует несколько столбцов, мы можем использовать across

 library(stringr)
df <- df %>%
     mutate(across(c(AvsDD, AvsWD, DDvsWD), ~ as.numeric(str_remove(., ".*\="))))