web-dev-qa-db-fra.com

Changer les cellules vides en "NA"

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
51
S Das

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")
76
Badoe

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))
28
sclarky

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

16
Holger Brandl

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)
8
ZKH

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)
}
3
Jerry T

Cela devrait faire l'affaire

dat <- dat %>% mutate_all(na_if,"")
2
Jonathan

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"

1
Todd D

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. 

0
user8333183

Vous pouvez également utiliser mutate_at dans dplyr

dat <- dat %>%
mutate_at(vars(colnames(.)),
        .funs = funs(ifelse(.=="", NA, as.character(.))))
0
camnesia