3.6 NULL, NaN, and Inf

Having learned the special missing value representation NA in Section 2.10, we will introduce three additional values to represent unexpected results, namely the NULL, NaN, and Inf. During the process, we will talk about their relationships to NA as well.

3.6.1 NULL

First, let’s take a look at str(), typeof() and length() of NULL.

str(NULL)
#>  NULL
typeof(NULL)
#> [1] "NULL"
length(NULL)
#> [1] 0

As you can see NULL only has class NULL with no values inside, hence the length is 0. It is worth to have comparison with NA regarding these items.

str(NA)
#>  logi NA
typeof(NA)
#> [1] "logical"
length(NA)
#> [1] 1

NULL is often returned by expressions and functions whose value is undefined.

a. Undefined field of a list

The first scenario of NULL is when you try to access an element of a list that is undefined.

my_list <- list(num = 1:3, char = c("a", "b"))
my_list$logi
#> NULL

Here, the result is NULL since logi is not a defined field in my_list.

b. Remove an element from a list

You can remove an element from a list by assign it the NULL value.

length(my_list)
#> [1] 2
my_list$num <- NULL
length(my_list)
#> [1] 1
my_list
#> $char
#> [1] "a" "b"

As you can see from the output, the element num is removed from my_list, leading to the length of my_list reduced by 1.

c. Initialize a list of certain length

The NULL value is useful to serve as the default initial value when you want to create a list of certain length using the vector() function.

my_list <- vector(mode = "list", length = 3)
my_list
#> [[1]]
#> NULL
#> 
#> [[2]]
#> NULL
#> 
#> [[3]]
#> NULL

It is worth mentioning that the vector() function is also useful to initialize a vector of given mode and length.

vector("numeric", length = 2)      ##default is 0
#> [1] 0 0
vector("logical", length = 2)      ##default is FALSE
#> [1] FALSE FALSE
vector("integer", length = 2)      ##default is 0
#> [1] 0 0
vector("character", length = 2)    ##default is empty string
#> [1] "" ""

To check if an element is NULL, you can’t use the logical comparison == NULL. Instead, you need to use the is.null() function.

a <- NULL
a == NULL      
#> logical(0)
is.null(a)
#> [1] TRUE

It is worth explaining the result of a == NULL is logical(0), representing a logical vector of length 0. The underlying reason is that NULL contains no value and is of length 0. As the == comparison returns a logical type object, hencing leading to a logical vector of length 0.

d. NULL values when creating a vector

If you create a vector with NULL values, all NULL values will be removed if there exists at least one regular values. If all of them are NULL values, only one of them will be kept. Note that there is fundamentally different from NA values. NA means the value is there, but the exact value is not available to us.

c(NULL, NULL, 1, NULL)
#> [1] 1
c(NULL, NULL)
#> NULL
c(NA, NA)
#> [1] NA NA

3.6.2 NaN

NaN, represents Not a Number, usually appears when you divide 0 by 0.

0/0
#> [1] NaN

Again, it is worth to look at str(), typeof() and length() of NaN.

str(NaN)
#>  num NaN
typeof(NaN)
#> [1] "double"
length(NaN)
#> [1] 1

As you can see from the results, NaN is a numeric vector of length 1, with the value NaN.

To check if a value is NaN, you can’t use the == NaN similar to checking missing values, instead you need to use the function is.nan().

a <- NaN
a == NaN       ##resulting an NA value
#> [1] NA
is.nan(a)      ##the correct way to check if the value is NaN
#> [1] TRUE
is.nan(c(NA, 1, NaN))
#> [1] FALSE FALSE  TRUE

3.6.3 Inf

The last special we want to introduce in this section is Inf, representing the value is positive infinity (\(\infty\)), corresponding to a proper mathematical limit. Similarly, we also have negative infinity: -Inf.

1/0
#> [1] Inf
-2/0
#> [1] -Inf
Inf > 3
#> [1] TRUE
Inf < -1
#> [1] FALSE
Inf + Inf
#> [1] Inf
-Inf + 1e10
#> [1] -Inf
1/0 - 1/0        #it equals 0/0, hencing NaN
#> [1] NaN

Again, it is worth to look at str(), typeof() and length() of Inf.

str(Inf)
#>  num Inf
typeof(Inf)
#> [1] "double"
length(Inf)
#> [1] 1

As you can see from the results, similar to NaN, Inf is a numeric vector of length 1, but with the value Inf.

To check whether a value is finite or infinite, you can use the is.finite() and is.infinite() function.

is.finite(1/0)
#> [1] FALSE
is.infinite(-3/0)
#> [1] TRUE

3.6.4 A comparison of the four special values in R

We would like to summarize the different behaviors of the four special values in R in the following table.

Summary NA NULL NaN Inf
class() "logical" "NULL" "numeric" "numeric"
length() 1 0 1 1
check is.na() is.null() is.nan() is.finite()

3.6.5 Exercises

Suppose x <- c(NA, NULL, Inf, NaN), answer the following questions. 1. What’s the length of x? 2. What’s the class and the storage type of x? 3. What’s the value of x + 1? Explain the reason for each element in the result. 4. What’s the value of x == x? Explain the reason for each element in the result.