title: R:purrr Understanding purrr extraction functions
body: <p>Here is a simple nested list with three levels, the ob level, each of which contains two v-level lists; the v level, which contains either one or two s-level objects, and the s level, each of which contains a character vector.</p>
  
  <pre><code>test_lst &lt;- list(ob1 = list(v1 = list(s1 = "X", s2 = paste0("A", 1:3)), v2 =  paste0("A", 4:8)), 
                   ob2 = list(v1 = list(s1 = "X", s2 = paste0("A", 9:11)), v2 =  paste0("A", 12:16)))
  </code></pre>
  
  <p>I am trying to understand how to access various levels of this list using purrr's map functions for extraction by name.  </p>
  
  <p>The help file on extraction provides an example using extraction by name of a list with no names at the top level. In this example the extraction function skips the  top level and uses the names to find elements at the second level.</p>
  
  <pre><code>l1 &lt;- list(list(a = 1L), list(a = NULL, b = 2L), list(b = 3L))
  l1 %&gt;% map("a", .default = "???")
  </code></pre>
  
  <p>A second example has no names and is indexed positionally. Again, however, the positions are positions within each top-level element of the list.</p>
  
  <pre><code>l2 &lt;- list(
   list(num = 1:3,     letters[1:3]),
   list(num = 101:103, letters[4:6]),
   list()
  )
  l2 %&gt;% map(c(2, 2))
  </code></pre>
  
  <p>In the first example above, suppose the top level were named. What happens?</p>
  
  <pre><code>l1 &lt;- list(one = list(a = 1L), two = list(a = NULL, b = 2L), three = list(b = 3L))
  l1 %&gt;% map("a", .default = "???")
  </code></pre>
  
  <p>The result is unchanged. 
  So I expect the result from </p>
  
  <pre><code>map(test_lst, c("v1", "s2"))
  </code></pre>
  
  <p>to likewise skip the top-level names and return the equivalent of </p>
  
  <pre><code>lapply(c("ob1", "ob2"), function(X)test_lst[[X]][["v1"]][["s2"]])
  
  [[1]]
  [1] "A1" "A2" "A3"
  
  [[2]]
  [1] "A9"  "A10" "A11
  </code></pre>
  
  <p>But that is not what happens. Instead, </p>
  
  <pre><code>find_vars &lt;- function(meta){
  map_chr(meta, c("v1", "s2")) -&gt; var_vecs
  var_vecs
  }
  
  find_vars(meta = test_lst)
  </code></pre>
  
  <p>yields the following error:</p>
  
  <pre><code> Error: Result 1 must be a single string, not a character vector of length 3
  Call `rlang::last_error()` to see a backtrace 
  7. stop(cnd) 
  6. abort(message, x = x, expected = expected, actual = actual, what = what, 
      arg = arg, ..., .subclass = c(.subclass, "purrr_error_bad_type")) 
  5. stop_bad_type(x, expected, actual = actual, what = what, arg = arg, 
      recycle = recycle, message = message, .subclass = c(.subclass, 
          "purrr_error_bad_vector")) 
  4. stop_bad_vector(x, expected_ptype, expected_length, what = what, 
      arg = arg, index = index, ..., recycle = recycle, message = message, 
      .subclass = c(.subclass, "purrr_error_bad_element_vector")) 
  3. purrr:::stop_bad_element_vector(c("A1", "A2", "A3"), 1, character(0), 
      1, what = "Result", arg = NULL, recycle = FALSE) 
  2. map_chr(meta, c("v1", "s2")) 
  1. find_vars(meta = test_lst) 
  
  &gt; rlang::last_error()
  &lt;error&gt;
  message: Result 1 must be a single string, not a character vector of length 3
  class:   `purrr_error_bad_element_vector`
  backtrace:
   1. global::find_vars(meta = test_lst)
   3. purrr:::stop_bad_element_vector(...)
   4. purrr:::stop_bad_vector(...)
   5. purrr:::stop_bad_type(...)
  Call `rlang::last_trace()` to see the full backtrace
  &gt; rlang::last_trace()
      x
   1. +-global::find_vars(meta = test_lst)
   2. | \-purrr::map_chr(meta, c("v1", "s2"))
   3. \-purrr:::stop_bad_element_vector(...)
   4.   \-purrr:::stop_bad_vector(...)
   5.     \-purrr:::stop_bad_type(...)
  </code></pre>
  
  <p>I would like to understand:</p>
  
  <ul>
  <li>why I get an error;</li>
  <li><p>what this particular error means: and</p></li>
  <li><p>how I could get a  result similar to the <code>lapply</code> results above using
  <code>purrr</code>.</p></li>
  </ul>