¿Por qué es match.call útil?
(1)
Una razón que es relevante aquí es que match.call
captura el lenguaje de la llamada sin evaluarla, y en este caso permite que lm
trate algunas de las variables "faltantes" como "opcionales". Considerar:
lm(x ~ y, data.frame(x=1:10, y=runif(10)))
Vs:
lm2 <- function (
formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...
) {
mf <- model.frame(
formula = formula, data = data, subset = subset, weights = weights
)
}
lm2(x ~ y, data.frame(x=1:10, y=runif(10)))
## Error in model.frame.default(formula = formula, data = data, subset = subset, :
## invalid type (closure) for variable ''(weights)''
En lm2
, dado que los weights
"faltan", pero aún se usan en weights=weights
, R intenta usar la función stats::weights
, que claramente no es lo que se pretendía. Podría evitar esto haciendo pruebas de ausencia de datos antes de llamar a model.frame
, pero en ese punto la match.call
comienza a verse bastante bien. Mira lo que pasa si debug
la llamada:
debug(lm2)
lm2(x ~ y, data.frame(x=1:10, y=runif(10)))
## debugging in: lm2(x ~ y, data.frame(x = 1:10, y = runif(10)))
## debug at #5: {
## mf <- model.frame(formula = formula, data = data, subset = subset,
## weights = weights)
## }
Browse[2]> match.call()
## lm2(formula = x ~ y, data = data.frame(x = 1:10, y = runif(10)))
match.call
no involucra los argumentos faltantes en absoluto.
Podría argumentar que los argumentos opcionales deberían haberse hecho explícitamente opcionales a través de los valores predeterminados, pero eso no es lo que sucedió aquí.
En el cuerpo de algunas funciones R, por ejemplo, veo llamadas a la función match.call
. Como dice la página de ayuda, cuando se usa dentro de una función match.call
devuelve una llamada donde se especifican los nombres de los argumentos; y se supone que esto es útil para pasar una gran cantidad de argumentos a otras funciones.
Por ejemplo, en la función lm
vemos una llamada a la función model.frame
function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...)
{
cl <- match.call()
mf <- match.call(expand.dots = FALSE)
m <- match(c("formula", "data", "subset", "weights", "na.action",
"offset"), names(mf), 0L)
mf <- mf[c(1L, m)]
mf$drop.unused.levels <- TRUE
mf[[1L]] <- quote(stats::model.frame)
mf <- eval(mf, parent.frame())
¿Por qué es esto más útil que hacer una llamada directa a model.frame
especificando los nombres de los argumentos como lo hago a continuación?
function (formula, data, subset, weights, na.action, method = "qr",
model = TRUE, x = FALSE, y = FALSE, qr = TRUE, singular.ok = TRUE,
contrasts = NULL, offset, ...)
{
mf <- model.frame(formula = formula, data = data,
subset = subset, weights = weights, subset = subset)
Tenga en cuenta que match.call
tiene otro uso que no discuto, almacenar la llamada en el objeto resultante.