How Can Library() Accept Both Quoted and Unquoted Strings

How can library() accept both quoted and unquoted strings

Great question!

Let's crack open the library() function to see how it works.

enter library into your interactive session to see the innards of the function.

The key parts of the function are from lines 186 to 197.

 if (!missing(package)) {
if (is.null(lib.loc))
lib.loc <- .libPaths()
lib.loc <- lib.loc[file.info(lib.loc)$isdir %in% TRUE]
if (!character.only)
package <- as.character(substitute(package))
if (length(package) != 1L)
stop("'package' must be of length 1")
if (is.na(package) || (package == ""))
stop("invalid package name")
pkgname <- paste("package", package, sep = ":")
newpackage <- is.na(match(pkgname, search()))

The key lines are

if (!character.only)
package <- as.character(substitute(package))

This means that as long as you don't change the character.only argument of library to TRUE, R will convert your package name into a character string and search for that.

Let's test:

 > library(ggplot2,character.only=TRUE)

outputs:

 Error in library(ggplot2, character.only = TRUE) :
object 'ggplot2' not found

whereas

library("ggplot2",character.only=TRUE)

loads the package.

Basically, no matter what you give the library() function as an argument for package it will convert it into a characters unless you specify character.only to be TRUE.

As Dason points out in the comments, a good use of the character.only argument is in cases where you have the library names stored as objects themselves.

How can you make tidyverse functions that support both quoted and unquoted arguments?

If it needs to work on both quoted/unquoted, use ensym

test_func <- function(variable) {  

dplyr::count(mtcars, !!rlang::ensym(variable))

}

-testing

test_func(cyl)
# cyl n
#1 4 11
#2 6 7
#3 8 14
test_func('cyl')
# cyl n
#1 4 11
#2 6 7
#3 8 14

NOTE: Better to have data also as an argument to the function

Quote an unquoted text in R

str <- "ACOT13,BIRC6,BOD1L1,CALM3,CDC42,CEP350,CIAO1,CLTA,CLTC,DIAPH1,DYNC2I1,DYNLL1,HAUS8,INO80,KIF22,KIFC1,MAD1L1,MAPK1,NSFL1C,NUP62,PLK3,PRC1,PRPF19,RMDN3,SEPTIN2,TUBG1,WDR62"
result <- strsplit(str,",")

Make a function (which uses data.table) that supports both quoted and unquoted arguments and then works in purrr::map (or lapply)

We can use :

library(data.table)

col_count2 <- function(dt, ...){
vars <- NULL
tryCatch({vars <- list(...)[[1]]}, error = function(e) {})
if(!is.character(vars)) vars <- as.character(substitute(list(...))[-1])
dt[, .N, by = vars]
}

identical(col_count2(dt_iris, Petal.Width, Species),
col_count2(dt_iris, c('Petal.Width', 'Species')))
#[1] TRUE

purrr::map(colnames(dt_iris), col_count2, dt = dt_iris)

#[[1]]
# Sepal.Length N
# 1: 5.1 9
# 2: 4.9 6
# 3: 4.7 2
# 4: 4.6 4
#....

#[[2]]
# Sepal.Width N
# 1: 3.5 6
# 2: 3.0 26
# 3: 3.2 13
# 4: 3.1 11
#....
#....

The use of quotation marks when loading a package in R

This is an example of non-standard evaluation. I'm not sure there is "best practice" regarding whether you should put packages in quotes. But

  • If you submit a paper to the Journal of Statistical Software they insist that package names are in quotes
  • Advanced R programming gives the downsides and also suggests against it.

The argument against

library(MASS)

is that for new users, it's hard to guess what

pkg = "MASS"
library(pkg)

will do.

Error: Quosures can only be unquoted within a quasiquotation context

It may be better to use ensym as we can pass either quoted or unquoted as input. The symbol is then converted to string with as_string, then we use the base R Extract method ([[) to extract the column as a vector to be used in wtd.chi.sq

xtab_func <- function(dat, col, target, wgt){
col <- rlang::as_string(ensym(col))
target <- rlang::as_string(ensym(target))
wgt <- rlang::as_string(ensym(wgt))
wtd.chi.sq(dat[[target]],dat[[col]], weight = dat[[wgt]])

}

-testing

xtab_func(data_in, 'Q50_1','pov','wgt1')
Chisq df p.value
7.3395092 4.0000000 0.1189981
xtab_func(data_in, Q50_1, pov, wgt1)
Chisq df p.value
7.3395092 4.0000000 0.1189981

NOTE: The dataset passed into the function is not quoted

How to properly pass quoted strings as part of URL input to httr:GET()?

I tried to find posts that covered this already, but there's a little detail here that threw me off. You can use utils::URLencode the encode the URL so that the quotation marks will be replaced with their percent-encoded equivalents.

URLencode has an argument repeated, which defaults to false:

repeated—logical: should apparently already-encoded URLs be encoded again?

An ‘apparently already-encoded URL’ is one containing %xx for two hexadecimal digits.

Your URL already has one piece encoded with %3A, the encoded version of :; because an encoded substring already exists, no further encoding is done by default. Instead, set repeated = FALSE, and the quotation marks get encoded as well:

library(httr)

urlinp <- 'https://www.uniprot.org/uniprot/?query=name%3A"dna+methyltransferase"'

URLencode(urlinp, repeated = FALSE)
#> [1] "https://www.uniprot.org/uniprot/?query=name%3A\"dna+methyltransferase\""
URLencode(urlinp, repeated = TRUE)
#> [1] "https://www.uniprot.org/uniprot/?query=name%253A%22dna+methyltransferase%22"

status_code(GET(URLencode(urlinp, repeated = TRUE)))
#> [1] 200

Syntax for loading vs. installing libraries.

library function takes package name as first argument. This name actually refers to the name passed as package argument rather than any value associated to that name. library function internally converts the package argument to a character literal (except when character.only is set to TRUE).

So,

plyr <- "dplyr"
library(plyr)

will undergo

if(!character.only)
package <- as.character(substitute(plyr))

to become

package <- "plyr"

install.packages takes a character vector as name(s) of packages to be installed.

dd <- "plyr"
install.packages(dd)

This would install plyr.

It is becauseinstall.packages don't do any such conversion with pkgs argument. So install.packages installs what pkgs refers to.



Related Topics



Leave a reply



Submit