studio hoverinfo change r

hoverinfo - Dividir argumentos `...` y distribuirlos a mĂșltiples funciones



r plotly axis format (3)

Usando la siguiente función foo() como un simple ejemplo, me gustaría distribuir los valores dados en ... dos funciones diferentes, si es posible.

foo <- function(x, y, ...) { list(sum = sum(x, ...), grep = grep("abc", y, ...)) }

En el siguiente ejemplo, me gustaría que na.rm pase a sum() y que el value pase a grep() . Pero recibo un error por un argumento no utilizado en grep() .

X <- c(1:5, NA, 6:10) Y <- "xyzabcxyz" foo(X, Y, na.rm = TRUE, value = TRUE) # Error in grep("abc", y, ...) : unused argument (na.rm = TRUE)

Parece que los argumentos fueron enviados a grep() primero. ¿Es eso correcto? Creo que R vería y evaluaría sum() primero, y devolvería un error para ese caso.

Además, al tratar de dividir los argumentos en ... , me encontré con problemas. sum() argumentos formales de sum() son NULL porque es un .Primitive , y por lo tanto no puedo usar

names(formals(sum)) %in% names(list(...))

Tampoco quiero suponer que los argumentos sobrantes de

names(formals(grep)) %in% names(list(...))

se pasan automáticamente a sum() .

¿Cómo puedo distribuir de manera segura y eficiente ... argumentos a múltiples funciones para que no se realicen evaluaciones innecesarias?

A largo plazo, me gustaría poder aplicar esto a funciones con una larga lista de ... argumentos, similares a los de download.file() y scan() .


  1. ¿Por qué grep error before sum ?

    Vea que la sum es mucho más complaciente con sus argumentos:

    X <- c(1:5, NA, 6:10) sum(X, na.rm = TRUE, value = TRUE) ## [1] 56

    No falla porque no le importan otros argumentos nombrados, por lo que el value = TRUE simplifica a TRUE que suma 1. Por cierto:

    sum(X, na.rm = TRUE) ## [1] 55

  2. ¿Cómo dividir ... a diferentes funciones?

    Un método (que es muy propenso a errores) es buscar los argumentos para las funciones objetivo. Por ejemplo:

    foo <- function(x, y, ...){ argnames <- names(list(...)) sumargs <- intersect(argnames, names(as.list(args(sum)))) grepargs <- intersect(argnames, names(as.list(args(grep)))) list(sum = do.call(sum, c(list(x), list(...)[sumargs])), grep = do.call(grep, c(list("abc", y), list(...)[grepargs]))) }

    Esto es propenso a error siempre que los argumentos que usa una función no sean informados correctamente por args , como los objetos S3. Como ejemplo:

    names(as.list(args(plot))) ## [1] "x" "y" "..." "" names(as.list(args(plot.default))) ## [1] "x" "y" "type" "xlim" "ylim" ## [6] "log" "main" "sub" "xlab" "ylab" ## [11] "ann" "axes" "frame.plot" "panel.first" "panel.last" ## [16] "asp" "..." ""

    En este caso, puede sustituir la función S3 apropiada. Debido a esto, no tengo una solución generalizada para esto (aunque no sé si existe o no).


Solo puede pasar el ... argumento a otra función, si esa otra función incluye todos los argumentos con nombre a los que pasa ... o si tiene un ... argumento en sí mismo. Entonces, para sum , esto no es problema ( args(sum) devuelve la function (..., na.rm = FALSE) ). Por otro lado, grep no tiene na.rm ni ... como argumento.

args(grep) # function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, # fixed = FALSE, useBytes = FALSE, invert = FALSE)

Esto no incluye ... y tampoco incluye un argumento con nombre na.rm Una solución simple es simplemente definir su propia función mygrep siguiente manera:

mygrep <- function (pattern, x, ignore.case = FALSE, perl = FALSE, value = FALSE, fixed = FALSE, useBytes = FALSE, invert = FALSE, ...) grep(pattern, x, ignore.case, perl, value, fixed, useBytes, invert)

Entonces parece funcionar:

foo <- function(x, y, ...){ list(sum = sum(x, ...), grep = mygrep("abc", y, ...)) } X <- c(1:5, NA, 6:10) Y <- "xyzabcxyz" foo(X, Y, na.rm = TRUE, value = TRUE) # $sum # [1] 56 # # $grep # [1] "xyzabcxyz"


Listas separadas Si realmente desea pasar diferentes conjuntos de parámetros a diferentes funciones, probablemente sea más limpio especificar listas separadas:

foo <- function(x, y, sum = list(), grep = list()) { list(sum = do.call("sum", c(x, sum)), grep = do.call("grep", c("abc", y, grep))) } # test X <- c(1:5, NA, 6:10) Y <- "xyzabcxyz" foo(X, Y, sum = list(na.rm = TRUE), grep = list(value = TRUE)) ## $sum ## [1] 55 ## ## $grep ## [1] "xyzabcxyz"

Lista híbrida / ... Una alternativa es que podríamos usar ... para uno de estos y luego especificar el otro como una lista, particularmente en el caso de que uno de ellos se use con frecuencia y el otro se use con poca frecuencia. El que se usa con frecuencia se pasará por ... y se usará con poca frecuencia a través de una lista. p.ej

foo <- function(x, y, sum = list(), ...) { list(sum = do.call("sum", c(x, sum)), grep = grep("abc", y, ...)) } foo(X, Y, sum = list(na.rm = TRUE), value = TRUE)

Aquí hay un par de ejemplos del enfoque híbrido de la R misma:

i) La función mapply toma ese enfoque usando ambos ... y una lista MoreArgs :

> args(mapply) function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE) NULL

ii) nls también toma este enfoque usando tanto ... como la lista de control :

> args(nls) function (formula, data = parent.frame(), start, control = nls.control(), algorithm = c("default", "plinear", "port"), trace = FALSE, subset, weights, na.action, model = FALSE, lower = -Inf, upper = Inf, ...) NULL