values - remove na in r data frame
¿Es posible establecer na.rm en TRUE globalmente? (4)
Hubo varias respuestas sobre cambiar el argumento de na.rm
nivel mundial ya. Solo quiero saber sobre partial()
función partial()
de los paquetes purrr
o pryr
. Usando esta función, puede crear una copia de la función existente con argumentos predefinidos :
library(purrr)
.mean <- partial(mean, na.rm = TRUE)
# Create sample vector
df <- c(1, 2, 3, 4, NA, 6, 7)
mean(df)
>[1] NA
.mean(df)
>[1] 3.833333
Podemos combinar este consejo con @agstudy answer y crear copias de todas las funciones con el argumento na.rm = TRUE
:
library(purrr)
# Create a vector of function names https://stackoverflow.com/a/17423072/9300556
Funs <- Filter(is.function,sapply(ls(baseenv()),get,baseenv()))
na.rm.f <- names(Filter(function(x) any(names(formals(args(x)))%in% ''na.rm''),Funs))
# Create strings. Dot "." is optional
fs <- lapply(na.rm.f,
function(x) paste0(".", x, "=partial(", x ,", na.rm = T)"))
eval(parse(text = fs))
Así que ahora, hay .max
, .max
, .max
, etc. en nuestro .GlobalEnv
. Puedes ejecutarlos:
.min(df)
> [1] 1
.max(df)
> [1] 7
.all(df)
> [1] TRUE
Para sobrescribir las funciones, simplemente elimine el punto "." de la llamada lapply. Inspirado por este blogpost
Para comandos como max
la opción na.rm
se establece de forma predeterminada en FALSE
. Entiendo por qué esta es una buena idea en general, pero me gustaría desactivarla durante un tiempo, es decir, durante una sesión.
¿Cómo puedo exigir que R configure na.rm = TRUE
siempre que sea una opción? encontré
options(na.action = na.omit)
pero esto no funciona. Sé que puedo establecer una opción na.rm=TRUE
para cada una de las funciones que escribo.
my.max <- function(x) {max(x, na.rm=TRUE)}
Pero eso no es lo que estoy buscando. Me pregunto si hay algo que pueda hacer de forma más global / universal en lugar de hacerlo para cada función.
No es posible cambiar na.rm
a TRUE
globalmente. (Ver el comentario de Hong Ooi debajo de la pregunta).
EDITAR:
Desafortunadamente, la respuesta que no desea es la única que funciona en general. No hay una opción global para esto, como para na.action, que solo afecta a las funciones de modelado como lm, glm, etc. (e incluso allí, no está garantizado que funcione en todos los casos). - Hong Ooi Jul 2 ''13 a las 6:23
Para mi paquete R, sobrescribí las funciones existentes mean
y sum
. Gracias al gran Ben (comentarios abajo), modifiqué mis funciones a esto:
mean <- function(x, ..., na.rm = TRUE) {
base::mean(x, ..., na.rm = na.rm)
}
Después de esto, mean(c(2, NA, 3)) = 2.5
lugar de NA
.
Y para la sum
:
sum <- function(x, ..., na.rm = TRUE) {
base::sum(x, ..., na.rm = na.rm)
}
Esto dará como resultado la sum(c(2, NA, 3)) = 5
lugar de NA
.
sum(c(2, NA, 3, NaN))
también funciona.
Una solución (peligrosa), es hacer lo siguiente:
- Listar todas las funciones que tienen
na.rm
como argumento. Aquí limité mi búsqueda al paquete base. - Busca cada función y agrega esta línea al principio de su cuerpo:
na.rm = TRUE
- Asigne la función de nuevo al paquete base.
Así que primero na.rm
en una lista (ll) todas las funciones que tienen na.rm
como argumento:
uses_arg <- function(x,arg)
is.function(fx <- get(x)) &&
arg %in% names(formals(fx))
basevals <- ls(pos="package:base")
na.rm.f <- basevals[sapply(basevals,uses_arg,''na.rm'')]
EDITAR mejor método para obtener todas las funciones de argumento de na.rm (gracias al comentario de mnel)
Funs <- Filter(is.function,sapply(ls(baseenv()),get,baseenv()))
na.rm.f <- names(Filter(function(x) any(names(formals(args(x)))%in% ''na.rm''),Funs))
Así que la lista de na.rm.f
ve así:
[1] "all" "any" "colMeans" "colSums"
[5] "is.unsorted" "max" "mean.default" "min"
[9] "pmax" "pmax.int" "pmin" "pmin.int"
[13] "prod" "range" "range.default" "rowMeans"
[17] "rowsum.data.frame" "rowsum.default" "rowSums" "sum"
[21] "Summary.data.frame" "Summary.Date" "Summary.difftime" "Summary.factor"
[25] "Summary.numeric_version" "Summary.ordered" "Summary.POSIXct" "Summary.POSIXlt"
Luego, para cada función que cambio el cuerpo, el código está inspirado en el paquete data.table
(FAQ 2.23) que agrega una línea al inicio de rbind.data.frame
y cbind.data.frame
.
ll <- lapply(na.rm.f,function(x)
{
tt <- get(x)
ss = body(tt)
if (class(ss)!="{") ss = as.call(c(as.name("{"), ss))
if(length(ss) < 2) print(x)
else{
if (!length(grep("na.rm = TRUE",ss[[2]],fixed=TRUE))) {
ss = ss[c(1,NA,2:length(ss))]
ss[[2]] = parse(text="na.rm = TRUE")[[1]]
body(tt)=ss
(unlockBinding)(x,baseenv())
assign(x,tt,envir=asNamespace("base"),inherits=FALSE)
lockBinding(x,baseenv())
}
}
})
No, si marca, la primera línea de cada función de nuestra lista:
unique(lapply(na.rm.f,function(x) body(get(x))[[2]]))
[[1]]
na.rm = TRUE