Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

User Defined Function not working in dplyr pipe

I have a dataset with proteins accession numbers (DataGranulomeTidy). I have written a function (extractInfo) in r to scrape some information of those proteins from the ncbi website. The function works as expected when I run it in a short "for" loop.

DataGranulomeTidy <- tibble(GIaccessionNumber = c("29436380", "4504165", "17318569"))

extractInfo <- function(GInumber){
    tempPage <- readLines(paste("https://www.ncbi.nlm.nih.gov/sviewer/viewer.fcgi?id=", GInumber, "&db=protein&report=genpept&conwithfeat=on&withparts=on&show-cdd=on&retmode=html&withmarkup=on&tool=portal&log$=seqview&maxdownloadsize=1000000", sep = ""), skipNul = TRUE)
    tempPage  <- base::paste(tempPage, collapse = "")
    Accession <- str_extract(tempPage, "(?<=ACCESSION).{3,20}(?=VERSION)")
    Symbol    <- str_extract(tempPage, "(?<=gene=\").{1,20}(?=\")")
    GeneID    <- str_extract(tempPage, "(?<=gov/gene/).{1,20}(?=\">)")
    out       <- paste(Symbol, Accession, GeneID, sep = "---")
    return(out)
}


for(n in 1:3){
    print(extractInfo(GInumber = DataGranulomeTidy$GIaccessionNumber[n]))
}
 [1] "MYH9---   AAH49849---4627"
 [1] "GSN---   NP_000168---2934"
 [1] "KRT1---   NP_006112---3848"

When I use the same function in a dplyr pipe I doesn't work and I can't figure our why.

 > DataGranulomeTidy %>% mutate(NewVar = extractInfo(.$GIaccessionNumber))
 Error in file(con, "r") : argumento 'description' inválido

At this point I could make things work without using the "pipe" operator by using the "for" operator but I would like so much to understand why the function does not work in the dplyr pipe.

like image 783
netlak Avatar asked Apr 17 '20 09:04

netlak


3 Answers

It is the cause that your UDF can't treat vector.

vectorized_extractInfo <- Vectorize(extractInfo, "GInumber")

DataGranulomeTidy %>% 
  mutate(NewVar = vectorized_extractInfo(GIaccessionNumber))
like image 143
cuttlefish44 Avatar answered Oct 13 '22 18:10

cuttlefish44


As @cuttlefish44 already pointed out, the problem is that your fun is not a vectorized fun. My approach uses purrr::map_chr. Another option would be to use dplyr::rowwise:

library(tidyverse)

DataGranulomeTidy <- tibble(GIaccessionNumber = c("29436380", "4504165", "17318569"))

extractInfo <- function(GInumber){
  tempPage <- readLines(paste("https://www.ncbi.nlm.nih.gov/sviewer/viewer.fcgi?id=", GInumber, "&db=protein&report=genpept&conwithfeat=on&withparts=on&show-cdd=on&retmode=html&withmarkup=on&tool=portal&log$=seqview&maxdownloadsize=1000000", sep = ""), skipNul = TRUE)
  tempPage  <- base::paste(tempPage, collapse = "")
  Accession <- str_extract(tempPage, "(?<=ACCESSION).{3,20}(?=VERSION)")
  Symbol    <- str_extract(tempPage, "(?<=gene=\").{1,20}(?=\")")
  GeneID    <- str_extract(tempPage, "(?<=gov/gene/).{1,20}(?=\">)")
  out       <- paste(Symbol, Accession, GeneID, sep = "---")
  return(out)
}

DataGranulomeTidy %>% mutate(NewVar = map_chr(GIaccessionNumber, extractInfo))
#> # A tibble: 3 x 2
#>   GIaccessionNumber NewVar                    
#>   <chr>             <chr>                     
#> 1 29436380          MYH9---   AAH49849---4627 
#> 2 4504165           GSN---   NP_000168---2934 
#> 3 17318569          KRT1---   NP_006112---3848

Created on 2020-04-17 by the reprex package (v0.3.0)

like image 33
stefan Avatar answered Oct 13 '22 20:10

stefan


There is a rentrez package for NCBI queries, for example:

library(rentrez)

protein <- entrez_summary("protein", id = 29436380)
protein$caption
# [1] "AAH49849"

links <- entrez_link(dbfrom = "protein", id = 29436380, db = "gene")
links$links$protein_gene
# [1] "4627"

gene <- entrez_summary("gene", id = links$links$protein_gene)
gene$name
# [1] "MYH9"

Wrap this up into a function, then we don't need to mess about with regex.

like image 27
zx8754 Avatar answered Oct 13 '22 19:10

zx8754