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 não acho que você queira / possa substituir por valores NULL, mas NA serve a esse propósito na linguagem R.
Perseguição
Respostas:
243
Substituindo todos os zeros para NA:
df[df ==0]<-NA
Explicação
1. Não é com o NULLque 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" ( NULLvalores).
Agora você pode substituir os zeros NULLem 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 NAe definindo o valor de usecomo "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 == 0vetorização. df == 0retorna (tente) uma matriz do mesmo tamanho que df, com as entradas TRUEe 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] <- NAproduz 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.
Qual seria a sintaxe equivalente para um objeto data.table?
precisa saber é o seguinte
6
Vejo que você obteve muitos votos, mas não acho que isso abranja adequadamente os casos extremos de colunas não numéricas com valores "0" que não foram solicitados para serem definidos como <NA>.
IRTFM
33
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
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2,5,TRUE), y = sample(0:2,5,TRUE))#-----
x y
102212311421500#replace zeros with NA
dat[dat==0]<-NA#-----
x y
1NA22123114215NANA
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:11502:21163:31124:41115:5126:61127:7108:8109:121910:2240
status[N ==0, N :=NA]
head(status,10)
origin destination N
1:11502:21163:31124:41115:5126:61127:71NA8:81NA9:121910:2240
Or for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA). Veja aqui uma discussão mais detalhada sobre o uso de data.table para encontrar e substituir valores.
JWilliman
4
Você pode substituir 0com NAapenas 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:5com o número de colunas no seu quadro de dados ou com 1:ncol(df).
Não tenho certeza se esta é a solução correta. E as colunas 6 e mais. Eles serão cortados.
userJT
É por isso que sugeri substituir 1:5por 1:ncol(df)no final. Não queria tornar a equação excessivamente complexa ou difícil de ler.
Alium Britt
mas e se nas colunas 6 e 7 - o tipo de dados for char e nenhuma substituição for feita. No meu problema, preciso substituir apenas nas colunas 12 a 15, mas o df inteiro possui 21 colunas (muitas não devem ser tocadas).
userJT
Para o seu quadro de dados você pode simplesmente mudar o 1:5que 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 }.
Alium Britt
0
Caso alguém chegue aqui via google procurando o oposto (ou seja, como substituir todos os NAs em um data.frame por 0), a resposta é
Respostas:
Substituindo todos os zeros para NA:
Explicação
1. Não é com o
NULL
que você deseja substituir os zeros. Como diz em?'NULL'
,que é único e, eu acho, pode ser visto como o objeto menos informativo e vazio. 1 Então não é tão surpreendente que
Ou seja, R não reserva nenhum espaço para esse objeto nulo. 2 Enquanto isso,
?'NA'
observamos queImportante,
NA
é de comprimento 1, de modo que R reserva algum espaço para ele. Por exemplo,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
, oucor
, que é, na verdade, equivalente a primeira substituição com zerosNA
e definindo o valor deuse
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 quedf
, com as entradasTRUE
eFALSE
. Além disso, também podemos passar essa matriz para o subconjunto[...]
(veja?'['
). Por fim, embora o resultado dedf[df == 0]
seja perfeitamente intuitivo, pode parecer estranho quedf[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.
fonte
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
fonte
Uma maneira alternativa sem a
[<-
função:Um exemplo de quadro de dados
dat
(copiado descaradamente da resposta de @ Chase):Os zeros podem ser substituídos
NA
por pelais.na<-
função:fonte
dplyr::na_if()
é uma opção:fonte
fonte
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]
fonte
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)
. Veja aqui uma discussão mais detalhada sobre o uso de data.table para encontrar e substituir valores.Você pode substituir
0
comNA
apenas em campos numéricos (ou seja, excluindo coisas como fatores), mas funciona em uma base coluna por coluna:Com uma função, você pode aplicar isso a todo o seu quadro de dados:
Embora você possa substituir o
1:5
com o número de colunas no seu quadro de dados ou com1:ncol(df)
.fonte
1:5
por1: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, como12: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 }
.Caso alguém chegue aqui via google procurando o oposto (ou seja, como substituir todos os NAs em um data.frame por 0), a resposta é
OU
Usando dplyr / tidyverse
fonte