Remover valores de NA de um vetor

191

Eu tenho um vetor enorme que possui alguns NAvalores e estou tentando encontrar o valor máximo nesse vetor (o vetor é todos os números), mas não posso fazer isso por causa dos NAvalores.

Como posso remover os NAvalores para poder calcular o máximo?

CodeGuy
fonte

Respostas:

265

Tentando ?max, você verá que ele realmente tem um na.rm =argumento, definido por padrão como FALSE. (Esse é o padrão comum para muitas outras funções R incluindo sum(), mean()etc.)

A configuração na.rm=TRUEfaz exatamente o que você está pedindo:

d <- c(1, 100, NA, 10)
max(d, na.rm=TRUE)

Se você deseja remover todos os NAs, use este idioma:

d <- d[!is.na(d)]

Uma nota final: Outras funções (por exemplo table(), lm()e sort()) tem NAargumentos relacionados com que usam nomes diferentes (e oferecem diferentes opções). Portanto, se NAvocê causar problemas em uma chamada de função, vale a pena procurar uma solução interna entre os argumentos da função. Eu descobri que geralmente há um já lá.

Josh O'Brien
fonte
Esta é uma péssima ideia. Ele falha e dá -Infpara dtodas as NAs.
user3932000
@ user3932000 Para deixar claro para outras pessoas, sua reclamação é realmente sobre como a função R básica max()se comporta (como, por exemplo, ao fazer max(c(NA, NA)). Pessoalmente, acho que seu comportamento é razoável; Espero que ele foi construído dessa maneira para que você obtenha o resultado esperado quando fazendo coisas comoa <- c(NA, NA); b <- 1:4; max(c(max(a, na.rm = TRUE), max(b, na.rm = TRUE)))
Josh O'Brien
@ user3932000 De maneira um tanto tangencial, um dos muitos pontos fortes de R como plataforma de análise de dados é o tratamento sofisticado de dados ausentes, resultado de muita reflexão cuidadosa por parte de seus autores. (Se você estiver interessado no assunto, veja aqui uma boa discussão sobre alguns dos problemas envolvidos, do ponto de vista dos programadores que estavam envolvidos na incorporação de NAinstalações de manipulação do tipo R no excelente pacote NumPy do Python .)
Josh O'Brien
@ user3932000: essa resposta é realmente ruim? O que você consideraria o máximo do conjunto nulo?
Cliff AB
@CliffAB Ele não tem um máximo. Você pode atribuir o máximo a -∞ (e o mínimo a + +), mas isso nem sempre é desejado ou intuitivo. Além disso, quando você remove todos os NAs de um vetor de NAs, esperaria um vetor vazio, não -∞.
User3932000 29/01
94

A na.omitfunção é o que muitas das rotinas de regressão usam internamente:

vec <- 1:1000
vec[runif(200, 1, 1000)] <- NA
max(vec)
#[1] NA
max( na.omit(vec) )
#[1] 1000
IRTFM
fonte
20

?maxmostra que há um parâmetro extra na.rmque você pode definir TRUE.

Além disso, se você realmente deseja remover os NAs, use algo como:

myvec[!is.na(myvec)]
Nick Sabbe
fonte
3
Eu acho que isso é melhor. na.rm e na.omit adicionam bastante lixo à saída.
MadmanLee
Exceto na.omittambém tem um método de quadro de dados, por isso é mais geral.
IRTFM 25/02/19
15

Você pode ligar max(vector, na.rm = TRUE). De maneira mais geral, você pode usar a na.omit()função

Michael Hoffman
fonte
14

Apenas no caso de alguém novo em R querer uma resposta simplificada para a pergunta original

Como posso remover valores de NA de um vetor?

Aqui está:

Suponha que você tenha um vetor da fooseguinte maneira:

foo = c(1:10, NA, 20:30)

correr length(foo)dá 22.

nona_foo = foo[!is.na(foo)]

length(nona_foo) é 21, porque os valores de NA foram removidos.

Remember is.na(foo)retorna uma matriz booleana; portanto, a indexação foocom o oposto desse valor fornecerá todos os elementos que não são NA.

Scott C Wilson
fonte
13

Use discardfrom purrr (funciona com listas e vetores).

discard(v, is.na) 

O benefício é que é fácil usar canos; alternativamente, use a função de subconjunto integrada [:

v %>% discard(is.na)
v %>% `[`(!is.na(.))

Observe que na.omitnão funciona em listas:

> x <- list(a=1, b=2, c=NA)
> na.omit(x)
$a
[1] 1

$b
[1] 2

$c
[1] NA
qwr
fonte
1

Fiz um rápido benchmark comparando as duas baseabordagens e, x[!is.na(x)]mais rápido do que na.omit. O usuário qwrsugeriu que eu tentasse purrr::dicardtambém - isso acabou sendo muito mais lento (embora eu tenha prazer em fazer comentários sobre minha implementação e teste!)

microbenchmark::microbenchmark(
  purrr::map(airquality,function(x) {x[!is.na(x)]}), 
  purrr::map(airquality,na.omit),
  purrr::map(airquality, ~purrr::discard(.x, .p = is.na)),
  times = 1e6)

Unit: microseconds
                                                     expr    min     lq      mean median      uq       max neval cld
 purrr::map(airquality, function(x) {     x[!is.na(x)] })   66.8   75.9  130.5643   86.2  131.80  541125.5 1e+06 a  
                          purrr::map(airquality, na.omit)   95.7  107.4  185.5108  129.3  190.50  534795.5 1e+06  b 
  purrr::map(airquality, ~purrr::discard(.x, .p = is.na)) 3391.7 3648.6 5615.8965 4079.7 6486.45 1121975.4 1e+06   c

Para referência, aqui está o teste original de x[!is.na(x)]vs na.omit:

microbenchmark::microbenchmark(
    purrr::map(airquality,function(x) {x[!is.na(x)]}), 
    purrr::map(airquality,na.omit), 
    times = 1000000)


Unit: microseconds
                                              expr  min   lq      mean median    uq      max neval cld
 map(airquality, function(x) {     x[!is.na(x)] }) 53.0 56.6  86.48231   58.1  64.8 414195.2 1e+06  a 
                          map(airquality, na.omit) 85.3 90.4 134.49964   92.5 104.9 348352.8 1e+06   b
jsavn
fonte
você deve tentarpurrr:discard
qwr