Voici le lien de mes données.
Mon objectif est d’attribuer "NA" à toutes les cellules vides, quelles que soient les valeurs catégoriques ou numériques. J'utilise na.strings = "". Mais cela n'affecte pas NA à toutes les cellules vides.
## 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
Je suppose que vous parlez de la ligne 5 de la colonne "sexe". Il se peut que dans le fichier data2.csv, la cellule contienne un espace et ne soit donc pas considérée comme vide par R.
En outre, j'ai remarqué que dans la colonne 5 "axes" et "porte" de la rangée 5, les valeurs d'origine lues à partir de data2.csv sont la chaîne "NA". Vous voudrez probablement traiter ceux-ci comme étant na.strings également. Pour faire ça,
dat2 <- read.csv("data2.csv", header=T, na.strings=c("","NA"))
MODIFIER:
J'ai téléchargé votre data2.csv. Oui, il y a un espace dans la rangée 5 colonne "sexe". Alors tu veux
na.strings=c(""," ","NA")
Vous pouvez utiliser gsub pour remplacer plusieurs mutations de empty, comme "" ou un espace, pour être NA:
data= data.frame(cats=c('', ' ', 'meow'), dogs=c("woof", " ", NA))
apply(data, 2, function(x) gsub("^$|^ $", NA, x))
Une solution plus conviviale utilisant dplyr
serait:
require(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))
Pour appliquer la correction à un sous-ensemble de colonnes uniquement, vous pouvez spécifier les colonnes d'intérêt à l'aide de la syntaxe de correspondance des colonnes de dplyr. Exemple: mutate_each(funs(empty_as_na), matches("Width"), Species)
Si votre table contient des dates, vous devriez envisager d'utiliser un more typesafe version de ifelse
J'ai récemment rencontré des problèmes similaires. C'est ce qui a fonctionné pour moi, si la variable est numérique, un simple df$Var[df$Var == ""] <- "NA"
devrait suffire. Mais si la variable est un facteur, vous devez d'abord la convertir en caractères, puis remplacer les cellules ""
par la valeur souhaitée et les reconvertir en facteurs. Ainsi, par exemple, votre variable de sexe, je suppose que ce serait un facteur et si vous souhaitez remplacer la cellule vide, je procéderais comme suit:
df$Var <- as.character(df$Var)
df$Var[df$Var==""] <- "NA"
df$Var <- as.factor(df$Var)
Ma fonction prend en compte le facteur, le vecteur de caractère et les attributs potentiels, si vous utilisez un paquet étranger ou étranger pour lire les fichiers externes. En outre, il permet de faire correspondre différentes chaînes na.strings auto-définies. Pour transformer toutes les colonnes, utilisez simplement lappy: df[] = lapply(df, blank2na, na.strings=c('','NA','na','N/A','n/a','NaN','nan'))
Voir plus les commentaires:
#' 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)
}
Cela devrait faire l'affaire
dat <- dat %>% mutate_all(na_if,"")
Bien que beaucoup des options ci-dessus fonctionnent bien, j’ai trouvé la coercition de variables non ciblées comme une variable chr
. L'utilisation de ifelse
et grepl
dans lapply
résout cet effet non ciblé (dans des tests limités). Utiliser l'expression régulière de slarky dans grepl
:
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)
Le problème de la contrainte à la classe de caractère:
df2 <- lapply(df, function(x) gsub("^$|^ $", NA, x))
lapply(df2, class)
$ x1
[1] "personnage"
$ x2 [1] "personnage"
Résolution avec utilisation de ifelse:
df3 <- lapply(df, function(x) ifelse(grepl("^$|^ $", x)==TRUE, NA, x))
lapply(df3, class)
$ x1
[1] "personnage"
$ x2 [1] "numérique"
Ne pourriez-vous pas simplement utiliser
dat <- read.csv("data2.csv",na.strings=" ",header=TRUE)
doit convertir tous les blancs en NA au fur et à mesure de la lecture des données. Assurez-vous de laisser un espace entre votre devis.
Vous pouvez également utiliser mutate_at
dans dplyr
dat <- dat %>%
mutate_at(vars(colnames(.)),
.funs = funs(ifelse(.=="", NA, as.character(.))))