varias truncar textuales texto suspensivos puntos oraciones los lineas ejemplos definicion con citas r function parameters ellipsis variadic

truncar - ¿Cómo usar la característica de puntos suspensivos de R cuando escribe su propia función?



puntos suspensivos ejemplos (6)

El lenguaje R tiene una característica ingeniosa para definir funciones que pueden tomar una cantidad variable de argumentos. Por ejemplo, la función data.frame toma cualquier número de argumentos, y cada argumento se convierte en los datos de una columna en la tabla de datos resultante. Ejemplo de uso:

> data.frame(letters=c("a", "b", "c"), numbers=c(1,2,3), notes=c("do", "re", "mi")) letters numbers notes 1 a 1 do 2 b 2 re 3 c 3 mi

La firma de la función incluye una elipsis, como esta:

function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE, stringsAsFactors = default.stringsAsFactors()) { [FUNCTION DEFINITION HERE] }

Me gustaría escribir una función que haga algo similar, tomar múltiples valores y consolidarlos en un único valor de retorno (así como también hacer algún otro procesamiento). Para hacer esto, necesito encontrar la manera de "descomprimir" ... desde los argumentos de la función dentro de la función. No se como hacer esto. La línea relevante en la definición de la función de data.frame es object <- as.list(substitute(list(...)))[-1L] , que no puedo entender.

Entonces, ¿cómo puedo convertir las elipsis de la firma de la función en, por ejemplo, una lista?

Para ser más específico, ¿cómo puedo escribir get_list_from_ellipsis en el siguiente código?

my_ellipsis_function(...) { input_list <- get_list_from_ellipsis(...) output_list <- lapply(X=input_list, FUN=do_something_interesting) return(output_list) } my_ellipsis_function(a=1:10,b=11:20,c=21:30)

Editar

Parece que hay dos maneras posibles de hacer esto. Son as.list(substitute(list(...)))[-1L] y list(...) . Sin embargo, estos dos no hacen exactamente lo mismo. (Para las diferencias, vea ejemplos en las respuestas.) ¿Puede alguien decirme cuál es la diferencia práctica entre ellos y cuál debería usar?


Creo que esto es lo que esperabas (siguiendo la figura). a1, a2, a3, a4 son algunos vectores arbitrarios, y ''catt'' es la función que toma cualquier número de argumentos y devuelve un vector concatenado de los argumentos de entrada.


Esto funciona como se esperaba La siguiente es una sesión interactiva:

> talk <- function(func, msg, ...){ + func(msg, ...); + } > talk(cat, c("this", "is", "a","message."), sep=":") this:is:a:message. >

Lo mismo, excepto con un argumento predeterminado:

> talk <- function(func, msg=c("Hello","World!"), ...){ + func(msg, ...); + } > talk(cat,sep=":") Hello:World! > talk(cat,sep=",", fill=1) Hello, World! >

Como puede ver, puede usar esto para pasar argumentos ''adicionales'' a una función dentro de su función si los valores predeterminados no son los que desea en un caso particular.


Leí respuestas y comentarios y veo que pocas cosas fueron mencionadas:

  1. data.frame usa la list(...) versión. Fragmento del código:

    object <- as.list(substitute(list(...)))[-1L] mrn <- is.null(row.names) x <- list(...)

    object se utiliza para hacer algo de magia con los nombres de columna, pero x se utiliza para crear data.frame final.
    Para el uso de un ... argumento no write.csv código match.call donde se usa match.call .

  2. Al escribir en el comentario, el resultado en la respuesta de Dirk no es una lista de listas. Es una lista de longitud 4, cuyos elementos son tipo de language . El primer objeto es un symbol - list , el segundo es la expresión 1:10 y así sucesivamente. Eso explica por qué [-1L] es necesario: elimina el symbol esperado de los argumentos proporcionados en ... (porque siempre es una lista).
    Como dice Dirk, el substitute devuelve "analizar el árbol de la expresión no evaluada".
    Cuando llamas my_ellipsis_function(a=1:10,b=11:20,c=21:30) entonces ... "crea" una lista de argumentos: list(a=1:10,b=11:20,c=21:30) y substitute por una lista de cuatro elementos:

    List of 4 $ : symbol list $ a: language 1:10 $ b: language 11:20 $ c: language 21:30

    El primer elemento no tiene un nombre y esto es [[1]] en la respuesta de Dirk. Logro estos resultados usando:

    my_ellipsis_function <- function(...) { input_list <- as.list(substitute(list(...))) str(input_list) NULL } my_ellipsis_function(a=1:10,b=11:20,c=21:30)

  3. Como arriba, podemos usar str para verificar qué objetos están en una función.

    my_ellipsis_function <- function(...) { input_list <- list(...) output_list <- lapply(X=input_list, function(x) {str(x);summary(x)}) return(output_list) } my_ellipsis_function(a=1:10,b=11:20,c=21:30) int [1:10] 1 2 3 4 5 6 7 8 9 10 int [1:10] 11 12 13 14 15 16 17 18 19 20 int [1:10] 21 22 23 24 25 26 27 28 29 30 $a Min. 1st Qu. Median Mean 3rd Qu. Max. 1.00 3.25 5.50 5.50 7.75 10.00 $b Min. 1st Qu. Median Mean 3rd Qu. Max. 11.0 13.2 15.5 15.5 17.8 20.0 $c Min. 1st Qu. Median Mean 3rd Qu. Max. 21.0 23.2 25.5 25.5 27.8 30.0

    Está bien. Veamos la versión substitute :

    my_ellipsis_function <- function(...) { input_list <- as.list(substitute(list(...))) output_list <- lapply(X=input_list, function(x) {str(x);summary(x)}) return(output_list) } my_ellipsis_function(a=1:10,b=11:20,c=21:30) symbol list language 1:10 language 11:20 language 21:30 [[1]] Length Class Mode 1 name name $a Length Class Mode 3 call call $b Length Class Mode 3 call call $c Length Class Mode 3 call call

    No es lo que necesitábamos Necesitará trucos adicionales para tratar con este tipo de objetos (como en write.csv ).

Si quieres usar ... entonces debes usarlo como en Shane answer, por list(...) .


Puede convertir las elipsis en una lista con list() y luego realizar sus operaciones en él:

> test.func <- function(...) { lapply(list(...), class) } > test.func(a="b", b=1) $a [1] "character" $b [1] "numeric"

Entonces su función get_list_from_ellipsis no es más que una list .

Un caso de uso válido para esto es en los casos en que desea pasar un número desconocido de objetos para la operación (como en su ejemplo de c() o data.frame() ). No es una buena idea usar el ... cuando conoces cada parámetro por adelantado, sin embargo, ya que agrega ambigüedad y complicaciones adicionales a la cadena del argumento (y hace que la firma de la función no sea clara para ningún otro usuario). La lista de argumentos es una pieza importante de documentación para usuarios de funciones.

De lo contrario, también es útil para casos en los que desee pasar parámetros a una subfunción sin exponerlos todos en sus propios argumentos de función. Esto se puede observar en la documentación de la función.


Solo para agregar a las respuestas de Shane y Dirk: es interesante comparar

get_list_from_ellipsis1 <- function(...) { list(...) } get_list_from_ellipsis1(a = 1:10, b = 2:20) # returns a list of integer vectors $a [1] 1 2 3 4 5 6 7 8 9 10 $b [1] 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

con

get_list_from_ellipsis2 <- function(...) { as.list(substitute(list(...)))[-1L] } get_list_from_ellipsis2(a = 1:10, b = 2:20) # returns a list of calls $a 1:10 $b 2:20

Tal como está, cualquiera de las versiones parece adecuada para sus propósitos en my_ellipsis_function , aunque la primera es claramente más simple.


Ya le diste la mitad de la respuesta. Considerar

R> my_ellipsis_function <- function(...) { + input_list <- as.list(substitute(list(...))) + } R> print(my_ellipsis_function(a=1:10, b=2:20)) [[1]] list $a 1:10 $b 11:20 R>

Entonces esto tomó dos argumentos a y b de la llamada y los convirtió a una lista. ¿No fue eso lo que pediste?