tablas - filtrar por casos completos en data.frame utilizando dplyr(eliminación de mayúsculas y minúsculas)
minusculas en r (6)
¿Es posible filtrar un data.frame para casos completos usando dplyr? complete.cases
con una lista de todas las variables funciona, por supuesto. Pero eso es a) detallado cuando hay muchas variables yb) imposible cuando los nombres de las variables no se conocen (por ejemplo, en una función que procesa cualquier data.frame).
library(dplyr)
df = data.frame(
x1 = c(1,2,3,NA),
x2 = c(1,2,NA,5)
)
df %.%
filter(complete.cases(x1,x2))
Aquí hay algunos resultados de referencia para la respuesta de Grothendieck. na.omit () toma 20 veces más tiempo que las otras dos soluciones. Creo que sería bueno si dplyr tuviera una función para esto tal vez como parte del filtro.
library(''rbenchmark'')
library(''dplyr'')
n = 5e6
n.na = 100000
df = data.frame(
x1 = sample(1:10, n, replace=TRUE),
x2 = sample(1:10, n, replace=TRUE)
)
df$x1[sample(1:n, n.na)] = NA
df$x2[sample(1:n, n.na)] = NA
benchmark(
df %>% filter(complete.cases(x1,x2)),
df %>% na.omit(),
df %>% (function(x) filter(x, complete.cases(x)))()
, replications=50)
# test replications elapsed relative
# 3 df %.% (function(x) filter(x, complete.cases(x)))() 50 5.422 1.000
# 1 df %.% filter(complete.cases(x1, x2)) 50 6.262 1.155
# 2 df %.% na.omit() 50 109.618 20.217
Esta es una función corta que le permite especificar columnas (básicamente todo lo que dplyr::select
puede comprender) que no debe tener ningún valor NA (modelado después de pandas df.dropna() ):
drop_na <- function(data, ...){
if (missing(...)){
f = complete.cases(data)
} else {
f <- complete.cases(select_(data, .dots = lazyeval::lazy_dots(...)))
}
filter(data, f)
}
[ drop_na ahora es parte de tidyr : lo anterior puede ser reemplazado por library("tidyr")
]
Ejemplos:
library("dplyr")
df <- data.frame(a=c(1,2,3,4,NA), b=c(NA,1,2,3,4), ac=c(1,2,NA,3,4))
df %>% drop_na(a,b)
df %>% drop_na(starts_with("a"))
df %>% drop_na() # drops all rows with NAs
Esto funciona para mí:
df %>%
filter(complete.cases(df))
O un poco más general:
library(dplyr) # 0.4
df %>% filter(complete.cases(.))
Esto tendría la ventaja de que los datos podrían haberse modificado en la cadena antes de pasarlos al filtro.
Otro punto de referencia con más columnas:
set.seed(123)
x <- sample(1e5,1e5*26, replace = TRUE)
x[sample(seq_along(x), 1e3)] <- NA
df <- as.data.frame(matrix(x, ncol = 26))
library(microbenchmark)
microbenchmark(
na.omit = {df %>% na.omit},
filter.anonymous = {df %>% (function(x) filter(x, complete.cases(x)))},
rowSums = {df %>% filter(rowSums(is.na(.)) == 0L)},
filter = {df %>% filter(complete.cases(.))},
times = 20L,
unit = "relative")
#Unit: relative
# expr min lq median uq max neval
# na.omit 12.252048 11.248707 11.327005 11.0623422 12.823233 20
#filter.anonymous 1.149305 1.022891 1.013779 0.9948659 4.668691 20
# rowSums 2.281002 2.377807 2.420615 2.3467519 5.223077 20
# filter 1.000000 1.000000 1.000000 1.0000000 1.000000 20
Prueba esto:
df %>% na.omit
o esto:
df %>% filter(complete.cases(.))
o esto:
library(tidyr)
df %>% drop_na
Si desea filtrar en función de la falta de una variable, use un condicional:
df %>% filter(!is.na(x1))
o
df %>% drop_na(x1)
Otras respuestas indican que las soluciones anteriores a na.omit
son mucho más lentas, pero tienen que na.omit
contra el hecho de que devuelve y fila los índices de las filas omitidas como el atributo na.action
mientras que las otras soluciones anteriores no lo hacen.
str(df %>% na.omit)
## ''data.frame'': 2 obs. of 2 variables:
## $ x1: num 1 2
## $ x2: num 1 2
## - attr(*, "na.action")= ''omit'' Named int 3 4
## ..- attr(*, "names")= chr "3" "4"
AÑADIDO Se ha actualizado para reflejar la última versión de dplyr y comentarios.
AÑADIDO Se ha actualizado para reflejar la última versión de tidyr y comentarios.
Solo para completar, dplyr::filter
puede evitarse por completo, pero aún así ser capaz de componer cadenas usando solo magrittr:extract
(un alias de [
):
library(magrittr)
df = data.frame(
x1 = c(1,2,3,NA),
x2 = c(1,2,NA,5))
df %>%
extract(complete.cases(.), )
La ventaja adicional es la velocidad, este es el método más rápido entre las variantes de filter
y na.omit
(probadas usando @Miha Trošt microbenchmarks).
prueba esto
df[complete.cases(df),] #output to console
O incluso esto
df.complete <- df[complete.cases(df),] #assign to a new data.frame
Los comandos anteriores se encargan de verificar la integridad de todas las columnas (variables) en su data.frame.