许多语言都有类似null或none这样的方式来表示不存在的值。由于 R 的设计初衷是处理大量(而且往往很杂乱)的数据,它有好几种表示“空无”的形式。
总体的目标是:一旦遇到缺失或可疑的值,就把它就地标记出来,然后继续运行,而不抛出异常。
如果一个值确实不存在,就用NULL表示。这大概最接近 C 或 Python 的处理方式。
v <- c() # zero-length vector
v
#> NULL
is.null(v)
#> [1] TRUE
在很多场景下,NULL值会被直接忽略:
c(2, 3, NULL, 5)
#> [1] 2 3 5
当值存在、但我们不知道它具体是什么时,就使用NA。例如,在统计道路上通行的车辆时,人工观察员可能请病假,自动传感器也可能出故障,但车流不会停下来。
v <- c(1, 2, NA, 4, 5)
v
#> [1] 1 2 NA 4 5
is.na(v) # test for data gaps
#> [1] FALSE FALSE TRUE FALSE FALSE
因此,NA是一个占位符,提醒人们需要决定如何处理这种情况。
如果数据中存在NA,统计函数默认通常会返回NA。
如果希望忽略这些值,可以用na.rm(NA remove)形参显式地表达这一点:
v <- c(1, 2, NA, 4, 5)
mean(v)
#> [1] NA
mean(v, na.rm = TRUE)
#> [1] 3
“Not a Number”的缩写,NaN用于在期望得到一个数字的地方标记出计算问题。
n <- c(0, 2, 4)
d <- c(0, 1, 2)
n / d
#> [1] NaN 2 2 # 0/0 is mathematically undefined
is.nan(n / d)
#> [1] TRUE FALSE FALSE
这并不是“无效”计算的唯一可能。
分子不为零时,除以零会返回Inf或-Inf,而不会抛出错误。
1 / 0
#> [1] Inf
也许有些出人意料,R 并没有检查向量是否为空的标准方法,不过一些第三方包实现了自己的函数,比如is.empty()。
就连生成一个空向量也不是那么直观。
在前面的某一节中我们看到,不带任何参数的c()返回的是NULL,而不是一个向量。
is.vector(c())
#> [1] FALSE
logical()或integer()这类函数接受一个指定所需长度的实参,这个长度可以是零。
z <- logical(0)
is.vector(z)
#> [1] TRUE
length(z)
#> [1] 0
我们也可以先生成一个向量,再删除其中的每一个元素,具体做法参见向量概念。 这样得到的是一个长度为 0 的、类型合适的向量。
v <- 5
v[-1] # delete the first element
#> numeric(0)