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?
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.
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
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
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
#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
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
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)
.