Load packages

Load purrr and repurrrsive, which contains recursive list examples.

library(purrr)
## install_github("jennybc/repurrrsive")
library(repurrrsive)

List inspection is very important and also fairly miserable. Below I offer interactive widgets for our example lists. If you wish to do the same locally, install the listviewer package.

library(listviewer)

Inspect and explore

Before you can apply a function to every element of a list, you’d better understand the list!

You need to develop a toolkit for list inspection. Be on the look out for:

  • What is the length of the list?
  • Are the components homogeneous, i.e. do they have the same overall structure, albeit containing different data?
  • Note the length, names, and types of the constituent objects.

I have no idea what’s in this list or what it’s structure is! Please send help.

Understand this is situation normal, especially when your list comes from querying a poorly documented APIs. This is often true even when your list has been created completely within R. How many of us perfectly understand the structure of a fitted linear model object? You just have to embark on a voyage of discovery and figure out what’s in there. Happy trails.

str()

str() can help with basic list inspection, although it’s still rather frustrating. Learn to love the max.level and list.len arguments. You can use them to keep the output of str() down to a manageable volume.

Once you begin to suspect or trust that your list is homogeneous, i.e. consists of sub-lists with similar structure, it’s often a good idea to do an in-depth study of a single element. In general, remember you can combine list inspection via str(..., list.len = x, max.level = y) with single [ and double [[ square bracket indexing.

The repurrrsive package provides examples of lists. We explore them below, to lay the groundwork for other lessons, and to demonstrate list inspection strategies.

listviewer

It’s often more helpful to explore such lists with an interactive widget, which we include below for all examples. If you installed the listviewer package, replicate this experience locally via listviewer::jsonedit(got_chars, mode = "view").

Wes Anderson color palettes

wesanderson is a simple list containing color palettes from the wesanderson package. Each component is a palette, named after a movie, and contains a character vector of colors as hexadecimal triplets.

str(wesanderson)
#> List of 15
#>  $ GrandBudapest : chr [1:4] "#F1BB7B" "#FD6467" "#5B1A18" "#D67236"
#>  $ Moonrise1     : chr [1:4] "#F3DF6C" "#CEAB07" "#D5D5D3" "#24281A"
#>  $ Royal1        : chr [1:4] "#899DA4" "#C93312" "#FAEFD1" "#DC863B"
#>  $ Moonrise2     : chr [1:4] "#798E87" "#C27D38" "#CCC591" "#29211F"
#>  $ Cavalcanti    : chr [1:5] "#D8B70A" "#02401B" "#A2A475" "#81A88D" ...
#>  $ Royal2        : chr [1:5] "#9A8822" "#F5CDB4" "#F8AFA8" "#FDDDA0" ...
#>  $ GrandBudapest2: chr [1:4] "#E6A0C4" "#C6CDF7" "#D8A499" "#7294D4"
#>  $ Moonrise3     : chr [1:5] "#85D4E3" "#F4B5BD" "#9C964A" "#CDC08C" ...
#>  $ Chevalier     : chr [1:4] "#446455" "#FDD262" "#D3DDDC" "#C7B19C"
#>  $ Zissou        : chr [1:5] "#3B9AB2" "#78B7C5" "#EBCC2A" "#E1AF00" ...
#>  $ FantasticFox  : chr [1:5] "#DD8D29" "#E2D200" "#46ACC8" "#E58601" ...
#>  $ Darjeeling    : chr [1:5] "#FF0000" "#00A08A" "#F2AD00" "#F98400" ...
#>  $ Rushmore      : chr [1:5] "#E1BD6D" "#EABE94" "#0B775E" "#35274A" ...
#>  $ BottleRocket  : chr [1:7] "#A42820" "#5F5647" "#9B110E" "#3F5151" ...
#>  $ Darjeeling2   : chr [1:5] "#ECCBAE" "#046C9A" "#D69C4E" "#ABDDDE" ...

listview wesanderson

Game of Thrones POV characters

got_chars is a list with information on the 29 point-of-view characters from the first five books in the Song of Ice and Fire series by George R. R. Martin. Retrieved from An API Of Ice And Fire. Each component corresponds to one character and contains 18 components which are named atomic vectors of various lengths and types.

str(got_chars, list.len = 3)
#> List of 29
#>  $ :List of 18
#>   ..$ url        : chr "http://www.anapioficeandfire.com/api/characters/1022"
#>   ..$ id         : int 1022
#>   ..$ name       : chr "Theon Greyjoy"
#>   .. [list output truncated]
#>  $ :List of 18
#>   ..$ url        : chr "http://www.anapioficeandfire.com/api/characters/1052"
#>   ..$ id         : int 1052
#>   ..$ name       : chr "Tyrion Lannister"
#>   .. [list output truncated]
#>  $ :List of 18
#>   ..$ url        : chr "http://www.anapioficeandfire.com/api/characters/1074"
#>   ..$ id         : int 1074
#>   ..$ name       : chr "Victarion Greyjoy"
#>   .. [list output truncated]
#>   [list output truncated]
str(got_chars[[1]], list.len = 8)
#> List of 18
#>  $ url        : chr "http://www.anapioficeandfire.com/api/characters/1022"
#>  $ id         : int 1022
#>  $ name       : chr "Theon Greyjoy"
#>  $ gender     : chr "Male"
#>  $ culture    : chr "Ironborn"
#>  $ born       : chr "In 278 AC or 279 AC, at Pyke"
#>  $ died       : chr ""
#>  $ alive      : logi TRUE
#>   [list output truncated]

listview got_chars

GitHub users and repositories

gh_users is a list with information on 6 GitHub users. gh_repos is a nested list, also of length 6, where each component is another list with information on up to 30 of that user’s repositories. Retrieved from the GitHub API.

str(gh_users, max.level = 1)
#> List of 6
#>  $ :List of 30
#>  $ :List of 30
#>  $ :List of 30
#>  $ :List of 30
#>  $ :List of 30
#>  $ :List of 30

listview gh_users

listview gh_repos

Exercises

  1. Read the documentation on str(). What does max.level control? Apply str() to wesanderson and/or got_chars and experiment with max.level = 0, max.level = 1, and max.level = 2. Which will you use in practice with deeply nested lists?
  2. What does the list.len argument of str() control? What is its default value? Call str() on got_chars and then on a single component of got_chars with list.len set to a value much smaller than the default. What range of values do you think you’ll use in real life?
  3. Call str() on got_chars, specifying both max.level and list.len.
  4. Call str() on the first element of got_chars, i.e. the first Game of Thrones character. Use what you’ve learned to pick an appropriate combination of max.level and list.len.

Creative Commons License