Aquí está el enlace de mis datos.
Mi objetivo es asignar "NA" a todas las celdas en blanco independientemente de los valores categóricos o numéricos. Estoy usando na.strings = "" . Pero no asigna NA a todas las celdas en blanco.
## reading the data
dat <- read.csv("data2.csv")
head(dat)
mon hr acc alc sex spd axles door reg cond1 drug1
1 8 21 No Control TRUE F 0 2 2 Physical Impairment (Eyes, Ear, Limb) A
2 7 20 No Control FALSE M 900 2 2 Inattentive D
3 3 9 No Control FALSE F 100 2 2 2004 Normal D
4 1 15 No Control FALSE M 0 2 2 Physical Impairment (Eyes, Ear, Limb) D
5 4 21 No Control FALSE 25 NA NA D
6 4 20 No Control NA F 30 2 4 Drinking Alcohol - Impaired D
inj1 PED_STATE st rac1
1 Fatal <NA> F <NA>
2 Moderate <NA> F <NA>
3 Moderate <NA> M <NA>
4 Complaint <NA> M <NA>
5 Complaint <NA> F <NA>
6 Moderate <NA> M <NA>
## using na.strings
dat2 <- read.csv("data2.csv", header=T, na.strings="")
head(dat2)
mon hr acc alc sex spd axles door reg cond1 drug1
1 8 21 No Control TRUE F 0 2 2 <NA> Physical Impairment (Eyes, Ear, Limb) A
2 7 20 No Control FALSE M 900 2 2 <NA> Inattentive D
3 3 9 No Control FALSE F 100 2 2 2004 Normal D
4 1 15 No Control FALSE M 0 2 2 <NA> Physical Impairment (Eyes, Ear, Limb) D
5 4 21 No Control FALSE 25 NA NA <NA> <NA> D
6 4 20 No Control NA F 30 2 4 <NA> Drinking Alcohol - Impaired D
inj1 PED_STATE st rac1
1 Fatal NA F NA
2 Moderate NA F NA
3 Moderate NA M NA
4 Complaint NA M NA
5 Complaint NA F NA
6 Moderate NA M NA
Respuestas:
Supongo que está hablando de la columna "sexo" de la fila 5. Podría darse el caso de que en el archivo data2.csv, la celda contenga un espacio y, por lo tanto, R. no la considere vacía.
Además, noté que en la fila 5 columnas "ejes" y "puerta", los valores originales leídos de data2.csv son la cadena "NA". Probablemente también desee tratarlos como na.strings. Para hacer esto,
dat2 <- read.csv("data2.csv", header=T, na.strings=c("","NA"))
EDITAR:
Descargué su data2.csv. Sí, hay un espacio en la columna "sexo" de la fila 5. Entonces quieres
na.strings=c(""," ","NA")
fuente
Puede usar gsub para reemplazar múltiples mutaciones de vacío, como "" o un espacio, para que sea NA:
data= data.frame(cats=c('', ' ', 'meow'), dogs=c("woof", " ", NA)) apply(data, 2, function(x) gsub("^$|^ $", NA, x))
fuente
gsub("^$", NA, trimws(x))
para manejar más de un espacio dentro de una celda. Sin embargo, tenga cuidado con ambos enfoques que convierten todas las columnas en variables de cadena / carácter (si aún no lo ha hecho).Una solución más amigable para la vista
dplyr
seríarequire(dplyr) ## fake blank cells iris[1,1]="" ## define a helper function empty_as_na <- function(x){ if("factor" %in% class(x)) x <- as.character(x) ## since ifelse wont work with factors ifelse(as.character(x)!="", x, NA) } ## transform all columns iris %>% mutate_each(funs(empty_as_na))
Para aplicar la corrección a solo un subconjunto de columnas, puede especificar columnas de interés utilizando la sintaxis de coincidencia de columnas de dplyr. Ejemplo:
mutate_each(funs(empty_as_na), matches("Width"), Species)
En caso de que su tabla contenga fechas, debería considerar usar una versión más segura de tipos de
ifelse
fuente
ifelse(x %in% c(""," ","NA"), NA, x)
.mutate_each
proporciona más flexibilidad y un patrón reutilizable.dplyr
es omnipresente en los flujos de trabajo R actuales y se acaba de agregar para que la respuesta sea autónoma. Creo quex!=""
es correcto aquí, ya que ni "" ni "NA" están en blanco. Además, la respuesta de @ sclarky falla para los marcos de datos que contienen números, y la de @ Badoe realmente no resuelve el problema para los marcos de datos existentes, por lo que ninguna otra respuesta parece responder la pregunta todavía de una manera genérica. Estoy feliz de conocer mejores soluciones.read.csv
para transformar celdas en blanco a NA al leer una tabla de un archivo. Sin embargo, dado que el título de la pregunta es "Cambiar las celdas en blanco a" NA "", una respuesta completa debería cubrir la situación en la que un data.frame ya está en el entorno y el usuario quiere deshacerse de las celdas en blanco.df %>% mutate_all(funs(empty_as_na)) %>% summarize_all(funs(sum(is.na(.))))
Si bien dplyr puede o no tener una adopción generalizada, goza de popularidad en un gran subconjunto de usuarios de R, incluido yo, así que gracias por esta solución.Esto debería funcionar
dat <- dat %>% mutate_all(na_if,"")
fuente
Recientemente me encontré con problemas similares, y esto es lo que funcionó para mí.
Si la variable es numérica, una simple
df$Var[df$Var == ""] <- NA
debería ser suficiente. Pero si la variable es un factor, primero debe convertirlo al carácter, luego reemplazar las""
celdas con el valor que desea y convertirlo nuevamente en factor. Entonces, por ejemplo, suSex
variable, supongo que sería un factor y si desea reemplazar la celda vacía, haría lo siguiente:df$Var <- as.character(df$Var) df$Var[df$Var==""] <- NA df$Var <- as.factor(df$Var)
fuente
Mi función tiene en cuenta el factor, el vector de caracteres y los atributos potenciales, si usa haven o un paquete externo para leer archivos externos. También permite hacer coincidir diferentes na.strings autodefinidos. Para transformar todas las columnas, simplemente use lappy:
df[] = lapply(df, blank2na, na.strings=c('','NA','na','N/A','n/a','NaN','nan'))
Ver más los comentarios:
#' Replaces blank-ish elements of a factor or character vector to NA #' @description Replaces blank-ish elements of a factor or character vector to NA #' @param x a vector of factor or character or any type #' @param na.strings case sensitive strings that will be coverted to NA. The function will do a trimws(x,'both') before conversion. If NULL, do only trimws, no conversion to NA. #' @return Returns a vector trimws (always for factor, character) and NA converted (if matching na.strings). Attributes will also be kept ('label','labels', 'value.labels'). #' @seealso \code{\link{ez.nan2na}} #' @export blank2na = function(x,na.strings=c('','.','NA','na','N/A','n/a','NaN','nan')) { if (is.factor(x)) { lab = attr(x, 'label', exact = T) labs1 <- attr(x, 'labels', exact = T) labs2 <- attr(x, 'value.labels', exact = T) # trimws will convert factor to character x = trimws(x,'both') if (! is.null(lab)) lab = trimws(lab,'both') if (! is.null(labs1)) labs1 = trimws(labs1,'both') if (! is.null(labs2)) labs2 = trimws(labs2,'both') if (!is.null(na.strings)) { # convert to NA x[x %in% na.strings] = NA # also remember to remove na.strings from value labels labs1 = labs1[! labs1 %in% na.strings] labs2 = labs2[! labs2 %in% na.strings] } # the levels will be reset here x = factor(x) if (! is.null(lab)) attr(x, 'label') <- lab if (! is.null(labs1)) attr(x, 'labels') <- labs1 if (! is.null(labs2)) attr(x, 'value.labels') <- labs2 } else if (is.character(x)) { lab = attr(x, 'label', exact = T) labs1 <- attr(x, 'labels', exact = T) labs2 <- attr(x, 'value.labels', exact = T) # trimws will convert factor to character x = trimws(x,'both') if (! is.null(lab)) lab = trimws(lab,'both') if (! is.null(labs1)) labs1 = trimws(labs1,'both') if (! is.null(labs2)) labs2 = trimws(labs2,'both') if (!is.null(na.strings)) { # convert to NA x[x %in% na.strings] = NA # also remember to remove na.strings from value labels labs1 = labs1[! labs1 %in% na.strings] labs2 = labs2[! labs2 %in% na.strings] } if (! is.null(lab)) attr(x, 'label') <- lab if (! is.null(labs1)) attr(x, 'labels') <- labs1 if (! is.null(labs2)) attr(x, 'value.labels') <- labs2 } else { x = x } return(x) }
fuente
También puede utilizar
mutate_at
endplyr
dat <- dat %>% mutate_at(vars(colnames(.)), .funs = funs(ifelse(.=="", NA, as.character(.))))
Seleccione columnas individuales para cambiar:
dat <- dat %>% mutate_at(vars(colnames(.)[names(.) %in% c("Age","Gender")]), .funs = funs(ifelse(.=="", NA, as.character(.))))
A partir de (dplyr 0.8.0 anterior), la forma en que debe escribirse ha cambiado. Antes de que fuera,
funs()
en.funs (funs(name = f(.))
. En lugar defuns
, ahora usamoslist (list(name = ~f(.)))
Tenga en cuenta que también hay una forma mucho más sencilla de enumerar los nombres de las columnas. (tanto el nombre de la columna como el índice de la columna funcionan)
dat <- dat %>% mutate_at(.vars = c("Age","Gender"), .funs = list(~ifelse(.=="", NA, as.character(.))))
fuente
Si bien muchas de las opciones anteriores funcionan bien, encontré que la coerción de variables no objetivo es
chr
problemática. Usarifelse
ygrepl
dentrolapply
resuelve este efecto fuera del objetivo (en pruebas limitadas). Usando la expresión regular de slarky engrepl
:set.seed(42) x1 <- sample(c("a","b"," ", "a a", NA), 10, TRUE) x2 <- sample(c(rnorm(length(x1),0, 1), NA), length(x1), TRUE) df <- data.frame(x1, x2, stringsAsFactors = FALSE)
El problema de la coacción a la clase de personaje:
df2 <- lapply(df, function(x) gsub("^$|^ $", NA, x)) lapply(df2, class)
PS
x1
[1] "personaje"$ x2 [1] "personaje"
Resolución con el uso de ifelse:
df3 <- lapply(df, function(x) ifelse(grepl("^$|^ $", x)==TRUE, NA, x)) lapply(df3, class)
PS
x1
[1] "personaje"$ x2 [1] "numérico"
fuente
Sospecho que todos ya tienen una respuesta, aunque en caso de que alguien venga a mirar, dplyr na_if () sería (desde mi perspectiva) el más eficiente de los mencionados:
# Import CSV, convert all 'blank' cells to NA dat <- read.csv("data2.csv") %>% na_if("")
Aquí hay un enfoque adicional que aprovecha la función read_delim de readr. Acabo de recoger (probablemente lo sepa, pero lo archivaré aquí para futuros usuarios). Esto es muy sencillo y más versátil que lo anterior, ya que puede capturar todo tipo de valores en blanco y relacionados con NA en su archivo csv:
dat <- read_csv("data2.csv", na = c("", "NA", "N/A"))
Tenga en cuenta el subrayado en la versión del lector frente a Base R "." en read_csv.
¡Ojalá esto ayude a alguien que deambula por la publicación!
fuente
¿No podrías simplemente usar
dat <- read.csv("data2.csv",na.strings=" ",header=TRUE)
debe convertir todos los espacios en blanco a NA a medida que se leen los datos, asegúrese de dejar un espacio entre la cita
fuente
Para aquellos que se preguntan acerca de una solución usando la forma data.table , aquí hay una para la que escribí una función, disponible en mi Github:
library(devtools) source_url("https://github.com/YoannPa/Miscellaneous/blob/master/datatable_pattern_substitution.R?raw=TRUE") dt.sub(DT = dat2, pattern = "^$|^ $",replacement = NA) dat2
La función recorre cada columna para identificar qué columna contiene coincidencias de patrones. Luego
gsub()
se aplica solo en columnas que contienen coincidencias para el patrón"^$|^ $"
, para sustituir coincidencias porNA
s.Seguiré mejorando esta función para que sea más rápida.
fuente
Esto funciona para mi.
dataset <- read.csv(file = "data.csv",header=TRUE,fill = T,na.strings = "")
fuente
Llame al
dplyr
paquete instalando desdecran
en rlibrary(dplyr) (file)$(colname)<-sub("-",NA,file$colname)
Convertirá toda la celda en blanco en una columna en particular como NA
Si la columna contiene "-", "", 0 como este, cámbielo en el código de acuerdo con el tipo de celda en blanco
Por ejemplo, si obtengo una celda en blanco como "" en lugar de "-", entonces use este código:
(file)$(colname)<-sub("", NA, file$colname)
fuente
dplyr
después de cargarla y no se escala bien a "todas las columnas" como OP está buscando.