107 votes

Comment remplacer les valeurs NA dans un tableau pour les colonnes sélectionnées

Il y a beaucoup de messages sur le remplacement des valeurs NA. Je sais qu'on peut remplacer les NA dans le tableau/cadre suivant par ce qui suit :

x[is.na(x)] < -0

Mais, que faire si je veux le restreindre à certaines colonnes uniquement? Permettez-moi de vous montrer un exemple.

Tout d'abord, commençons par un jeu de données.

set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
                b=sample(c(1,2,NA), 10, replace=T), 
                c=sample(c(1:5,NA), 10, replace=T))

Ce qui donne :

    a  b  c
1   1 NA  2
2   2  2  2
3   2  1  1
4   2 NA  1
5  NA  1  2
6   2 NA  5
7   1  1  4
8   1  1 NA
9   2  1  5
10  2  1  1

D'accord, je veux simplement restreindre le remplacement aux colonnes 'a' et 'b'. Ma tentative a été la suivante :

x[is.na(x), 1:2] < -0

et :

x[is.na(x[1:2])] < -0

Ce qui ne fonctionne pas.

Ma tentative avec data.table, où y ← data.table(x), n'allait évidemment jamais fonctionner :

y[is.na(y[,list(a,b)]), ]

Je veux passer les colonnes à l'intérieur de l'argument is.na mais évidemment ça ne fonctionnerait pas.

Je voudrais faire cela dans un data.frame et une data.table. Mon objectif final est de recoder de 1 à 2 en 0 à 1 dans 'a' et 'b' tout en laissant 'c' tel qu'il est, car ce n'est pas une variable logique. J'ai plein de colonnes donc je ne veux pas le faire une par une. Et, je voudrais juste savoir comment faire cela.

Avez-vous des suggestions?

145voto

flodel Points 41487

Vous pouvez faire :

x[, 1:2][is.na(x[, 1:2])] <- 0

ou mieux (selon moi), utilisez les noms de variable :

x[c("a", "b")][is.na(x[c("a", "b")])] <- 0

Dans les deux cas, 1:2 ou c("a", "b") peuvent être remplacés par un vecteur pré-défini.

51voto

sbha Points 1948

S'appuyant sur la réponse de @Robert McDonald à tidyr::replace_na(), voici quelques options de dplyr pour contrôler les colonnes dans lesquelles les NA sont remplacés :

library(tidyverse)

# par type de colonne :
x %>%
  mutate_if(is.numeric, ~replace_na(., 0))

# sélectionner les colonnes définies dans vars(col1, col2, ...) :
x %>%
  mutate_at(vars(a, b, c), ~replace_na(., 0))

# toutes les colonnes :
x %>%
  mutate_all(~replace_na(., 0))

44voto

eddi Points 17947

Modifier 2020-06-15

Depuis data.table 1.12.4 (Oct 2019), data.table gagne deux fonctions pour faciliter cela : nafill et setnafill.

nafill opère sur les colonnes :

cols = c('a', 'b')
y[ , (cols) := lapply(.SD, nafill, fill=0), .SDcols = cols]

setnafill opère sur les tables (les remplacements se font par référence/sur place)

setnafill(y, cols=cols, fill=0)
# imprimer y pour montrer l'effet
y[]

Ceci sera également plus efficace que les autres options ; voir ?nafill pour plus d'informations, les versions de l'imputation de NA portant la dernière observation en avant (LOCF) et la prochaine observation en arrière (NOCB) pour les séries temporelles.


Ceci fonctionnera pour votre version de data.table :

for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]

Alternativement, comme le souligne David Arenburg ci-dessous, vous pouvez utiliser set (avantage supplémentaire - vous pouvez l'utiliser sur un data.frame ou un data.table) :

for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)

21voto

Robert McDonald Points 569

Ceci est maintenant banal dans tidyr avec replace_na(). La fonction semble fonctionner pour les data.tables ainsi que pour les data.frames :

tidyr::replace_na(x, list(a=0, b=0))

3voto

Amy M Points 302

Pas sûr si c'est plus concis, mais cette fonction permet également de trouver et de remplacer les valeurs NA (ou toute autre valeur de votre choix) dans les colonnes sélectionnées d'un data.table :

update.mat <- function(dt, cols, criteria) {
  require(data.table)
  x <- as.data.frame(which(criteria==TRUE, arr.ind = TRUE))
  y <- as.matrix(subset(x, x$col %in% which((names(dt) %in% cols), arr.ind = TRUE)))
  y
}

Pour l'appliquer :

y[update.mat(y, c("a", "b"), is.na(y))] <- 0

La fonction crée une matrice des colonnes et des lignes sélectionnées (coordonnées des cellules) qui répondent aux critères d'entrée (dans ce cas is.na == TRUE).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X