Eu tenho um quadro de dados com algumas colunas numéricas. Alguma linha tem um valor 0 que deve ser considerado nulo na análise estatística. Qual é a maneira mais rápida de substituir todo o valor 0 para NULL em R?
Eu tenho um quadro de dados com algumas colunas numéricas. Alguma linha tem um valor 0 que deve ser considerado nulo na análise estatística. Qual é a maneira mais rápida de substituir todo o valor 0 para NULL em R?
Respostas:
Substituindo todos os zeros para NA:
df[df == 0] <- NA
Explicação
1. Não é com o NULL
que você deseja substituir os zeros. Como diz em ?'NULL'
,
NULL representa o objeto nulo em R
que é único e, eu acho, pode ser visto como o objeto menos informativo e vazio. 1 Então não é tão surpreendente que
data.frame(x = c(1, NULL, 2))
# x
# 1 1
# 2 2
Ou seja, R não reserva nenhum espaço para esse objeto nulo. 2 Enquanto isso, ?'NA'
observamos que
NA é uma constante lógica de comprimento 1 que contém um indicador de valor ausente. O NA pode ser coagido a qualquer outro tipo de vetor, exceto bruto.
Importante, NA
é de comprimento 1, de modo que R reserva algum espaço para ele. Por exemplo,
data.frame(x = c(1, NA, 2))
# x
# 1 1
# 2 NA
# 3 2
Além disso, a estrutura do quadro de dados exige que todas as colunas tenham o mesmo número de elementos para que não haja "buracos" ( NULL
valores).
Agora você pode substituir os zeros NULL
em um quadro de dados no sentido de remover completamente todas as linhas que contêm pelo menos um zero. Quando se utiliza, por exemplo, var
, cov
, ou cor
, que é, na verdade, equivalente a primeira substituição com zeros NA
e definindo o valor de use
como "complete.obs"
. Normalmente, porém, isso é insatisfatório, pois leva à perda de informações extras.
2. Em vez de executar algum tipo de loop, na solução eu uso a df == 0
vetorização. df == 0
retorna (tente) uma matriz do mesmo tamanho que df
, com as entradas TRUE
e FALSE
. Além disso, também podemos passar essa matriz para o subconjunto [...]
(veja ?'['
). Por fim, embora o resultado de df[df == 0]
seja perfeitamente intuitivo, pode parecer estranho que df[df == 0] <- NA
produz o efeito desejado. O operador de atribuição <-
nem sempre é tão inteligente e não funciona dessa maneira com outros objetos, mas com quadros de dados; veja ?'<-'
.
1 O conjunto vazio na teoria dos conjuntos parece de alguma forma relacionado.
2 Outra semelhança com a teoria dos conjuntos: o conjunto vazio é um subconjunto de todos os conjuntos, mas não reservamos espaço para ele.
Deixe-me supor que seu data.frame é uma mistura de tipos de dados diferentes e nem todas as colunas precisam ser modificadas.
para modificar apenas as colunas 12 a 18 (do total de 21), faça isso
df[, 12:18][df[, 12:18] == 0] <- NA
Uma maneira alternativa sem a [<-
função:
Um exemplo de quadro de dados dat
(copiado descaradamente da resposta de @ Chase):
dat
x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0
Os zeros podem ser substituídos NA
por pela is.na<-
função:
is.na(dat) <- !dat
dat
x y
1 NA 2
2 1 2
3 1 1
4 2 1
5 NA NA
#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
Como alguém pediu a versão Data.Table disso e porque a solução data.frame fornecida não funciona com data.table, estou fornecendo a solução abaixo.
Basicamente, use o :=
operador ->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
Você pode substituir 0
com NA
apenas em campos numéricos (ou seja, excluindo coisas como fatores), mas funciona em uma base coluna por coluna:
col[col == 0 & is.numeric(col)] <- NA
Com uma função, você pode aplicar isso a todo o seu quadro de dados:
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))
Embora você possa substituir o 1:5
com o número de colunas no seu quadro de dados ou com 1:ncol(df)
.
1:5
por 1:ncol(df)
no final. Não queria tornar a equação excessivamente complexa ou difícil de ler.
1:5
que os números das colunas que pretende alterar, como 12:15
, mas se você queria confirmar que ela só vai afetar colunas numéricas, em seguida, só embrulhar a segunda linha da função em uma instrução if, como este: if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
.