usar - r language apply data frame
lapply con la funciĆ³n "$" (2)
Para el primer ejemplo, puedes hacer:
lapply(dflist, `$.data.frame`, "a")
Para el segundo, use la función de acceso a la slot()
lapply(mylist, "slot", "tab")
No estoy seguro de por qué el envío de métodos no funciona en el primer caso, pero la sección Note
de ?lapply
aborda este mismo problema de su envío de métodos borked para funciones primitivas como $
:
Note:
[...]
For historical reasons, the calls created by ‘lapply’ are
unevaluated, and code has been written (e.g., ‘bquote’) that
relies on this. This means that the recorded call is always of
the form ‘FUN(X[[i]], ...)’, with ‘i’ replaced by the current
(integer or double) index. This is not normally a problem, but it
can be if ‘FUN’ uses ‘sys.call’ or ‘match.call’ or if it is a
primitive function that makes use of the call. This means that it
is often safer to call primitive functions with a wrapper, so that
e.g. ‘lapply(ll, function(x) is.numeric(x))’ is required to ensure
that method dispatch for ‘is.numeric’ occurs correctly.
Digamos que tengo una lista de data.frames
dflist <- list(data.frame(a=1:3), data.frame(b=10:12, a=4:6))
Si quiero extraer la primera columna de cada elemento de la lista, puedo hacer
lapply(dflist, `[[`, 1)
# [[1]]
# [1] 1 2 3
#
# [[2]]
# [1] 10 11 12
¿Por qué no puedo usar la función "$" de la misma manera?
lapply(dflist, `$`, "a")
# [[1]]
# NULL
#
# [[2]]
# NULL
Pero ambos funcionan:
lapply(dflist, function(x) x$a)
`$`(dflist[[1]], "a")
Me doy cuenta de que en este caso uno podría usar
lapply(dflist, `[[`, "a")
pero estaba trabajando con un objeto S4 que no parecía permitir la indexación a través de [[
. Por ejemplo
library(adegenet)
data(nancycats)
catpop <- genind2genpop(nancycats)
mylist <- list(catpop, catpop)
#works
catpop[[1]]$tab
#doesn''t work
lapply(mylist, "$", "tab")
# Error in slot(x, name) :
# no slot of name "..." for this object of class "genpop"
#doesn''t work
lapply(mylist, "[[", "tab")
# Error in FUN(X[[1L]], ...) : this S4 class is not subsettable
Por lo tanto, parece que este problema tiene más que ver con $
y la forma en que normalmente espera nombres sin comillas como el segundo parámetro en lugar de cadenas. Mira este ejemplo
dflist <- list(
data.frame(a=1:3, z=31:33),
data.frame(b=10:12, a=4:6, z=31:33)
)
lapply(dflist,
function(x, z) {
print(paste("z:",z));
`$`(x,z)
},
z="a"
)
Vemos los resultados
[1] "z: a"
[1] "z: a"
[[1]]
[1] 31 32 33
[[2]]
[1] 31 32 33
por lo que el valor de z
se establece en "a", pero $
no está evaluando el segundo parámetro. De modo que devuelve la columna "z" en lugar de la columna "a". Esto lleva a este interesante conjunto de resultados
a<-"z"; `$`(dflist[[1]], a)
# [1] 1 2 3
a<-"z"; `$`(dflist[[1]], "z")
# [1] 31 32 33
a<-"z"; `$.data.frame`(dflist[[1]], a)
# [1] 31 32 33
a<-"z"; `$.data.frame`(dflist[[1]], "z")
# [1] 31 32 33
Cuando llamamos $.data.frame
directamente estamos evitando el deparsing estándar que ocurre en la primitiva antes del envío (que ocurre cerca de here en la fuente).
La captura agregada con lapply
es que pasa argumentos a la función a través del ...
mecanismo. Por ejemplo
lapply(dflist, function(x, z) sys.call())
# [[1]]
# FUN(X[[2L]], ...)
# [[2]]
# FUN(X[[2L]], ...)
Esto significa que cuando se invoca $
, desparece el ...
en la cadena "..."
. Esto explica este comportamiento
dflist<- list(data.frame(a=1:3, "..."=11:13, check.names=F))
lapply(dflist, `$`, "a")
# [[1]]
# [1] 11 12 13
Lo mismo sucede cuando intentas usar ...
tú mismo
f<-function(x,...) `$`(x, ...);
f(dflist[[1]], "a");
# [1] 11 12 13
`$`(dflist[[1]], "a")
# [1] 1 2 3