从向量中删除NA值

235
我有一个很大的向量,其中有几个NA值,我想要找到该向量中的最大值(向量中的元素都是数字),但由于存在NA值,我无法完成这个任务。
请问如何去除NA值,以便能够计算最大值?
8个回答

316

试着使用 ?max,你会发现它实际上有一个na.rm =参数,默认设置为FALSE。(这是许多其他R函数(包括sum()mean()等)的常见默认值。)

na.rm=TRUE设置为所需的操作:

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

如果你真的想要移除所有的 NA,可以使用以下习语:

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

最后注意事项:其他函数(例如table()lm()sort())具有与NA相关的参数,这些参数使用不同的名称(并提供不同的选项)。因此,如果NA在函数调用中引起问题,则值得检查函数参数中是否存在内置解决方案。我发现通常已经有一个解决方案。


1
这是一个非常糟糕的想法。对于所有NAs的“d”,它会失败并给出“-Inf”。 - user3932000
@user3932000 为了让其他人清楚,你的抱怨实际上是关于基本 R 函数 max() 的行为(例如,在执行 max(c(NA, NA)) 时)。就个人而言,我认为它的行为是合理的;我预计它是这样构建的,以便在执行诸如 a <- c(NA, NA); b <- 1:4; max(c(max(a, na.rm = TRUE), max(b, na.rm = TRUE))) 这样的操作时获得预期的结果。 - Josh O'Brien
1
@user3932000 有点离题,R作为数据分析平台之一的许多优势之一是其对缺失数据的复杂处理,这是其作者经过深思熟虑的结果。(如果您对此感兴趣,请参见此处以了解一些涉及问题的良好讨论,从程序员的角度来看,他们正在将类似于R的NA处理功能纳入Python的出色NumPy包中。) - Josh O'Brien
@user3932000:那个答案真的很糟糕吗?你认为空集的最大值是多少? - Cliff AB
@CliffAB 它没有最大值。你可以将最大值赋为-∞(最小值为+∞),但这并不总是理想的或直观的。此外,当你从一个由NA组成的向量中删除所有的NA时,你期望得到一个空向量,而不是-∞。 - user3932000
1
@user3932000:我想有些人可能认为他们想从max(NULL)得到任何东西,但对我来说,“-Inf”是一个非常数学上一致的答案。 - Cliff AB

113

na.omit函数是许多回归例程内部使用的函数:

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

48
使用discard from 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

27

?max向你展示了一个额外的参数na.rm,你可以将其设置为TRUE.

除此之外,如果你真的想要移除NAs,只需使用类似以下的代码:

myvec[!is.na(myvec)]

3
我认为这是最好的。na.rm和na.omit会给输出添加很多无用的内容。 - MadmanLee
1
除了 na.omit 还有一个数据框方法,因此更通用。 - IRTFM

19

以防有刚学R的人想要简单的回答原问题:

如何从向量中删除NA值?

这里是答案:

假设你有一个名为foo的向量,如下所示:

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

运行length(foo)会得到22。

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

nona_foo的长度是21,因为NA值已被删除。

请记住,is.na(foo)返回一个布尔矩阵,因此使用相反的值索引foo将给出所有非NA元素。


16
您可以调用 max(vector, na.rm = TRUE)。更一般地,您可以使用 na.omit() 函数。

6
我进行了一个快速的基准测试,比较了两种“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

你应该尝试使用purrr:discard - qwr

1

另一种选项是使用complete.cases,像这样:

d <- c(1, 100, NA, 10)
result <- complete.cases(d)
output <- d[result]
output
#> [1]   1 100  10
max(output)
#> [1] 100

使用reprex v2.0.2于2022年8月26日创建


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接