Удалить значения NA из вектора

192

У меня есть огромный вектор, который имеет пару NAзначений, и я пытаюсь найти максимальное значение в этом векторе (вектор это все числа), но я не могу сделать это из-за NAзначений.

Как я могу удалить NAзначения, чтобы я мог вычислить максимум?

CodeGuy
источник

Ответы:

266

Попробовав ?max, вы увидите, что у него действительно есть na.rm =аргумент, установленный по умолчанию в FALSE. (Это стандартное значение по умолчанию для многих других функций R, включая sum(), mean()и т. Д.)

Установка na.rm=TRUEделает только то, что вы просите:

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

Если вы хотите удалить все NAs, используйте вместо этого эту идиому:

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

Последнее замечание: другие функции (например table(), lm()и sort()) имеют NAсвязанные аргументы, которые используют разные имена (и предлагают разные варианты). Поэтому, если у NAвас проблемы с вызовом функции, стоит проверить наличие встроенного решения среди аргументов функции. Я обнаружил, что обычно он там уже есть.

Джош О'Брайен
источник
Это очень плохая идея. Это терпит неудачу и дает -Infдля dвсех НС.
user3932000
@ user3932000 Просто чтобы быть понятным для других, ваша жалоба действительно о том, как max()ведет себя функция base R (как, например, при выполнении max(c(NA, NA)). Лично я думаю, что его поведение разумно; Я ожидаю, что он был построен таким образом, чтобы вы получили ожидаемый результат при выполнении таких вещей, какa <- c(NA, NA); b <- 1:4; max(c(max(a, na.rm = TRUE), max(b, na.rm = TRUE)))
Джош О'Брайен
@ user3932000 Несколько тангенциально, один из многих сильных R в качестве платформы для анализа данных является сложной обработкой недостающих данных, результат много осторожной мысли со стороны ее авторов. (Если вам интересна эта тема, посмотрите здесь для хорошего обсуждения некоторых связанных с этим вопросов, с точки зрения программистов, которые занимались включением средств обработки R-like NAв превосходный пакет Python NumPy .)
Джош О'Брайен
@ user3932000: этот ответ действительно плох? Что бы вы считали максимумом нулевого множества?
Клифф AB
@CliffAB Это не максимум. Вы можете назначить максимум -∞ (а min + +), но это не всегда желательно или интуитивно понятно. Кроме того, когда вы удаляете все NAs из вектора NAs, вы ожидаете пустой вектор, а не -∞.
user3932000
94

Эта na.omitфункция используется многими внутренними процедурами регрессии:

vec <- 1:1000
vec[runif(200, 1, 1000)] <- NA
max(vec)
#[1] NA
max( na.omit(vec) )
#[1] 1000
IRTFM
источник
20

?maxпоказывает, что есть дополнительный параметр, na.rmкоторый вы можете установить TRUE.

Кроме того, если вы действительно хотите удалить NAs, просто используйте что-то вроде:

myvec[!is.na(myvec)]
Ник Саббе
источник
3
Я думаю, что это лучше. na.rm и na.omit добавляют немного мусора к выводу.
MadmanLee
Кроме того, na.omitтакже есть метод dataframe, поэтому является более общим.
IRTFM
15

Вы можете позвонить max(vector, na.rm = TRUE). В более общем смысле, вы можете использовать na.omit()функцию.

Майкл Хоффман
источник
14

На всякий случай, если кто-то новичок в R хочет получить упрощенный ответ на оригинальный вопрос

Как я могу удалить значения NA из вектора?

Вот:

Предположим, у вас есть вектор fooследующим образом:

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

Бег length(foo)дает 22.

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

length(nona_foo) 21, потому что значения NA были удалены.

Помните, is.na(foo)возвращает булеву матрицу, поэтому индексирование fooс обратным значением даст вам все элементы, которые не являются NA.

Скотт К Уилсон
источник
13

Использование discardот purrr (работает со списками и векторами).

discard(v, is.na) 

Преимущество заключается в простоте использования труб; в качестве альтернативы используйте встроенную функцию поднабора [:

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

Обратите внимание, что na.omitне работает со списками:

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

$b
[1] 2

$c
[1] NA
qwr
источник
2

Я провел быстрый тест, сравнивая два baseподхода, и оказалось, что x[!is.na(x)]он быстрее, чем na.omit. Пользователь qwrпредложил purrr::dicardтакже попробовать - это оказалось намного медленнее (хотя я с радостью прокомментирую мою реализацию и тест!)

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

Для справки вот оригинальный тест x[!is.na(x)]против 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
источник
Вы должны попробоватьpurrr:discard
QWR