Il y a beaucoup d'articles sur le remplacement des valeurs de NA. Je suis conscient que l'on pourrait remplacer les AN dans le tableau/cadre suivant par:
x[is.na(x)]<-0
Mais que se passe-t-il si je veux le limiter à certaines colonnes? Laissez-moi vous montrer un exemple.
Commençons par un ensemble 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))
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
Ok, je veux seulement limiter le remplacement aux colonnes 'a' et 'b'. Ma tentative était:
x[is.na(x), 1:2]<-0
et:
x[is.na(x[1:2])]<-0
Ce qui ne marche pas.
Ma tentative de data.table, où y<-data.table(x)
, ne fonctionnait évidemment jamais:
y[is.na(y[,list(a,b)]), ]
Je veux passer des colonnes dans l'argument is.na mais cela ne fonctionnerait évidemment pas.
Je voudrais faire ceci dans un data.frame et un data.table. Mon objectif final est de recoder le 1: 2 à 0: 1 dans 'a' et 'b' tout en conservant le 'c' tel qu'il est, puisqu'il ne s'agit pas d'une variable logique. J'ai un tas de colonnes donc je ne veux pas le faire un par un. Et j'aimerais juste savoir comment faire ça.
Avez-vous des suggestions?
Tu peux faire:
x[, 1:2][is.na(x[, 1:2])] <- 0
ou mieux (IMHO), utilisez les noms de variables:
x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
Dans les deux cas, 1:2
ou c("a", "b")
peut être remplacé par un vecteur prédéfini.
Cela fonctionnera pour votre version data.table
:
for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]
Comme le souligne David Arenburg ci-dessous, vous pouvez également utiliser set
(avantage supplémentaire - vous pouvez l'utiliser soit sur data.frame
, soit sur data.table
):
for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)
Ceci est maintenant trivial dans tidyr avec replace_na (). La fonction semble fonctionner pour data.tables ainsi que data.frames:
tidyr::replace_na(x, list(a=0, b=0))
Vous ne savez pas si cela est plus concis, mais cette fonction trouvera et autorisera également le remplacement des NA (ou de toute valeur que vous préférez) dans les colonnes sélectionnées d'un fichier 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 de cellule) qui répondent aux critères d'entrée (dans ce cas, is.na == TRUE).
En vous appuyant sur la réponse tidyr::replace_na()
de @Robert McDonald's, voici quelques options dplyr
pour contrôler les colonnes remplacées par les NA
s:
library(tidyverse)
# by column type:
x %>%
mutate_if(is.numeric, ~replace_na(., 0))
# select columns defined in vars(col1, col2, ...):
x %>%
mutate_at(vars(a, b, c), ~replace_na(., 0))
# all columns:
x %>%
mutate_all(~replace_na(., 0))
Pour une colonne spécifique, il existe une alternative avec sapply
DF <- data.frame(A = letters[1:5],
B = letters[6:10],
C = c(2, 5, NA, 8, NA))
DF_NEW <- sapply(seq(1, nrow(DF)),
function(i) ifelse(is.na(DF[i,3]) ==
TRUE,
0,
DF[i,3]))
DF[,3] <- DF_NEW
DF
We can solve it in data.table way with tidyr::repalce_na function and lapply
library(data.table)
library(tidyr)
setDT(df)
df[,c("a","b","c"):=lapply(.SD,function(x) replace_na(x,0)),.SDcols=c("a","b","c")]
In this way,we can also solve paste cloumns with NA string.First, we replace_na(x,""),then we can use stringr::str_c to combine columns!