web-dev-qa-db-fra.com

Remplacer toutes les valeurs 0 par NA

J'ai un dataframe avec quelques colonnes numériques. Certaines lignes ont une valeur 0 qui doit être considérée comme nulle en analyse statistique. Quel est le moyen le plus rapide de remplacer toute la valeur 0 par NULL dans R?

118
Seen

Remplacer tous les zéros par NA:

df[df == 0] <- NA



Explication

1. Ce n'est pas NULL ce que vous devriez vouloir remplacer par des zéros. Comme il est dit dans ?'NULL',

NULL représente l'objet nul en R

ce qui est unique et, je suppose, peut être considéré comme l’objet le moins informatif et le plus vide.1 Cela devient alors pas si surprenant que

data.frame(x = c(1, NULL, 2))
#   x
# 1 1
# 2 2

C'est-à-dire que R ne réserve aucun espace pour cet objet nul.2 Pendant ce temps, en regardant ?'NA' on voit que

NA est une constante logique de longueur 1 qui contient un indicateur de valeur manquante. NA peut être contraint à tout autre type de vecteur sauf brut.

Il est important de noter que NA a la longueur 1, de sorte que R lui réserve de l'espace. Par exemple.,

data.frame(x = c(1, NA, 2))
#    x
# 1  1
# 2 NA
# 3  2

En outre, la structure de trame de données requiert que toutes les colonnes aient le même nombre d'éléments, de sorte qu'il ne puisse y avoir de "trous" (c'est-à-dire, NULL valeurs).

Vous pouvez maintenant remplacer les zéros par NULL dans un cadre de données, c'est-à-dire supprimer complètement toutes les lignes contenant au moins un zéro. Lorsque vous utilisez, par exemple, var, cov ou cor, cela revient en fait à remplacer d'abord les zéros par NA et à définir la valeur de use comme "complete.obs". Cependant, cela n’est généralement pas satisfaisant car cela entraîne une perte d’information supplémentaire.

2. Au lieu d'exécuter une sorte de boucle, dans la solution, j'utilise df == 0 la vectorisation. df == 0 renvoie (essayez-le) une matrice de la même taille que df, avec les entrées TRUE et FALSE. De plus, nous sommes également autorisés à transmettre cette matrice au sous-ensemble [...] (voir ?'['). Enfin, si le résultat de df[df == 0] est parfaitement intuitif, il peut sembler étrange que df[df == 0] <- NA donne l'effet souhaité. L’opérateur d’assignation <- n’est en effet pas toujours aussi intelligent et ne fonctionne pas de cette façon avec certains autres objets, mais il le fait avec des trames de données; voir ?'<-'.


1 L'ensemble vide dans la théorie des ensembles se sent en quelque sorte lié.
2 Autre similitude avec la théorie des ensembles: l'ensemble vide est un sous-ensemble de chaque ensemble, mais nous ne lui réservons aucun espace.

206
Julius Vainora

Laissez-moi supposer que votre data.frame est un mélange de différents types de données et que toutes les colonnes ne doivent pas être modifiées.

pour modifier uniquement les colonnes 12 à 18 (sur un total de 21), il suffit de le faire

df[, 12:18][df[, 12:18] == 0] <- NA
27
userJT

Une autre manière sans la fonction [<-:

Exemple de trame de données dat (copiée sans vergogne à partir de la réponse de @ Chase):

dat

  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

Les zéros peuvent être remplacés par NA par la fonction is.na<-:

is.na(dat) <- !dat


dat

   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA
22
Sven Hohenstein

dplyr::na_if() est une option:

library(dplyr)  

df <- data_frame(col1 = c(1, 2, 3, 0),
                 col2 = c(0, 2, 3, 4),
                 col3 = c(1, 0, 3, 0),
                 col4 = c('a', 'b', 'c', 'd'))

na_if(df, 0)
# A tibble: 4 x 4
   col1  col2  col3 col4 
  <dbl> <dbl> <dbl> <chr>
1     1    NA     1 a    
2     2     2    NA b    
3     3     3     3 c    
4    NA     4    NA d
18
sbha
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

#replace zeros with NA
dat[dat==0] <- NA
#-----
   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA
14
Chase

Parce que quelqu'un a demandé la version de Data.Table, et que la solution data.frame donnée ne fonctionne pas avec data.table, je propose la solution ci-dessous.

Fondamentalement, utilisez l'opérateur := -> DT[x == 0, x := NA]

library("data.table")

status = as.data.table(occupationalStatus)

head(status, 10)
    Origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1  0
 8:      8           1  0
 9:      1           2 19
10:      2           2 40


status[N == 0, N := NA]

head(status, 10)
    Origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1 NA
 8:      8           1 NA
 9:      1           2 19
10:      2           2 40
12
Reilstein

Vous pouvez remplacer 0 par NA uniquement dans les champs numériques (c'est-à-dire en excluant des facteurs tels que les facteurs), mais cela fonctionne colonne par colonne:

col[col == 0 & is.numeric(col)] <- NA

Avec une fonction, vous pouvez l’appliquer à l’ensemble de votre bloc de données:

changetoNA <- function(colnum,df) {
    col <- df[,colnum]
    if (is.numeric(col)) {  #edit: verifying column is numeric
        col[col == -1 & is.numeric(col)] <- NA
    }
    return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))

Bien que vous puissiez remplacer 1:5 par le nombre de colonnes de votre trame de données ou par 1:ncol(df).

4
Alium Britt