Inspecting the environment

In R, every expression is evaluated within a specific environment. An environment is a collection of symbols and their bindings. When we bind a value to a symbol, call a function, or refer to a name, R will find the symbols in the current environment. If you type commands in the RStudio console, your commands are evaluated in the Global Environment.

For example, when we start a fresh R session in a terminal or RStudio, we start working within an empty global environment. In other words, there is no symbol defined in this environment. If we run x <- c(1, 2, 3), the numeric vector c(1, 2, 3) is bound to symbol x in the global environment. Then, the global environment has one binding that maps x to the vector c(1, 2, 3). In other words, if you evaluate x, then you will get its value.

Inspecting existing symbols

In addition to manipulating vectors and lists as we did in the previous chapter, we need to know some basic functions to inspect and manipulate our working environment. The most basic but useful function to inspect the collection of objects we are working with is objects(). The function returns a character vector of the names of existing objects in the current environment.

In a fresh R session, there should not be any symbol in the current environment:

objects()
## character(0)

Let's assume we create the following objects:

x <- c(1, 2, 3)
y <- c("a", "b", "c")
z <- list(m = 1:5, n = c("x", "y", "z"))

Then, you will get a character vector of the existing object names:

objects()
## [1] "x" "y" "z"

Many developers prefer ls() as an alias of objects():

ls()
## [1] "x" "y" "z"

In most cases, especially when you are working in RStudio, you don't have to use objects() or ls() to see what symbols have been created because the Environment pane shows all symbols available in the global environment:

Inspecting existing symbols

The Environment pane shows symbols and their values in a compact representation. You can interact with objects in it by expanding a list or data frame and viewing the vectors inside.

In addition to the list view, the Environment pane also provides an alternative grid view. The grid view shows not only the names, types, and the value structures of existing objects, but also their object sizes:

Inspecting existing symbols

Although the Environment pane in RStudio makes it straightforward to inspect all existing variables, objects() or ls() can be still useful when RStudio is not available, when you write a function to work with their names, or the objects are provided dynamically in different manners.

Viewing the structure of an object

In the Environment pane, the compact representation of an object comes from the str() function, which prints the structure of a given object.

For example, when str() is applied to a simple numeric vector, it shows its type, positions, and a preview of its values:

x
## [1] 1 2 3
str(x)
## num [1:3] 1 2 3

If the vector has more than 10 elements, str() will only show the first 10:

str(1:30)
## int [1:30] 1 2 3 4 5 6 7 8 9 10 ...

For a list, directly evaluating it in the console or using print() will show the elements in a verbose form:

z
## $m
## [1] 1 2 3 4 5
## 
## $n
## [1] "x" "y" "z"

Alternatively, str() shows its type, length, and the structure preview of the elements:

str(z)
## List of 2
## $ m: int [1:5] 1 2 3 4 5
## $ n: chr [1:3] "x" "y" "z"

Let's assume we created the following nested list:

nested_list <- list(m = 1:15, n = list("a", c(1, 2, 3)),
   p = list(x = 1:10, y = c("a", "b")),
   q = list(x = 0:9, y = c("c", "d")))

Directly printing will show all its elements and tell us how we can access them which can be long and unnecessary in most cases:

nested_list
## $m
## [1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
## 
## $n
## $n[[1]]
## [1] "a"
## 
## $n[[2]]
## [1] 1 2 3
## 
## 
## $p
## $p$x
## [1] 1 2 3 4 5 6 7 8 9 10
## 
## $p$y
## [1] "a" "b"
## 
## 
## $q
## $q$x
## [1] 0 1 2 3 4 5 6 7 8 9
## 
## $q$y
## [1] "c" "d"

To get a compact representation that is easier to view and work with, call str() with a list:

str(nested_list)
## List of 4
## $ m: int [1:15] 1 2 3 4 5 6 7 8 9 10 ...
## $ n:List of 2
## ..$ : chr "a"
## ..$ : num [1:3] 1 2 3
## $ p:List of 2
## ..$ x: int [1:10] 1 2 3 4 5 6 7 8 9 10
## ..$ y: chr [1:2] "a" "b"
## $ q:List of 2
## ..$ x: int [1:10] 0 1 2 3 4 5 6 7 8 9
## ..$ y: chr [1:2] "c" "d"

While str() shows the structure of an object, ls.str() shows the structure of the current environment:

ls.str()
## nested_list : List of 4
## $ m: int [1:15] 1 2 3 4 5 6 7 8 9 10 ...
## $ n:List of 2
## $ p:List of 2
## $ q:List of 2
## x : num [1:3] 1 2 3
## y : chr [1:3] "a" "b" "c"
## z : List of 2
## $ m: int [1:5] 1 2 3 4 5
## $ n: chr [1:3] "x" "y" "z"

Its functionality is similar to that of the Environment pane in RStudio and can be useful when you need to inspect a customized environment or only show the structures of some particular variables.

One filter for ls.str() is the mode argument. You can show the structures of all values that are list objects:

ls.str(mode = "list")
## nested_list : List of 4
## $ m: int [1:15] 1 2 3 4 5 6 7 8 9 10 ...
## $ n:List of 2
## $ p:List of 2
## $ q:List of 2
## z : List of 2
## $ m: int [1:5] 1 2 3 4 5
## $ n: chr [1:3] "x" "y" "z"

The other filter is the pattern argument, which specifies the pattern of the names to match. The pattern is expressed in a regular expression. If you want to show the structures of all variables whose names contain only one character, you can run the following command:

ls.str(pattern = "^\w$")
## x : num [1:3] 1 2 3
## y : chr [1:3] "a" "b" "c"
## z : List of 2
## $ m: int [1:5] 1 2 3 4 5
## $ n: chr [1:3] "x" "y" "z"

If you want to show the structures of all list objects whose names contain only one character, you can use both pattern and mode at the same time:

ls.str(pattern = "^\w$", mode = "list")
## z : List of 2
## $ m: int [1:5] 1 2 3 4 5
## $ n: chr [1:3] "x" "y" "z"

If you're put off by commands such as ^\w$, don't worry. This pattern matches all strings in the form of (string begin)(any one word character like a, b, c)(string end). We will cover this powerful tool in Chapter 6Working with Strings.

Removing symbols

So far, we have only created symbols. Sometimes, it can be useful to remove them. The remove() function, or equivalently rm(), removes existing symbols from the environment.

Before removing x, the symbols in the environment are as follows:

ls()
## [1] "nested_list" "x" "y" "z"

Then, we will use rm() to remove x from the environment:

rm(x)
ls()
## [1] "nested_list" "y" "z"

Note that the function also works with variable names in strings. Therefore, rm("x") has exactly the same effect. We can also remove multiple symbols in one function call:

rm(y, z)
ls()
## [1] "nested_list"

If the symbol to be removed does not exist in the environment, a warning will appear:

rm(x)
## Warning in rm(x): object 'x' not found

The rm() function can also remove all symbols specified by a character vector of symbol names:

p <- 1:10
q <- seq(1, 20, 5)
v <- c("p", "q")
rm(list = v)
## [1] "nested_list" "v"

If we want to clear all the bindings in an environment, we can combine rm() and ls() and call the function like this:

rm(list = ls())
ls()
## character(0)

Now there's no symbol in the environment.

In many cases, removing symbols is not necessary, but it can be useful to remove very large objects that occupy a big area of memory. If R feels memory pressure, it will clean up unused objects with no bindings.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset