Traverse a list of structure to find the depths and positions of its elements that satisfy a predicate.

depths(
    list,
    predicate,
    bare = TRUE,
    ...
)
depths_string(
    list,
    predicate,
    bare = TRUE,
    ...
)

Arguments

list

A list, data.frame, or vector.

predicate

A function that evaluates to TRUE or FALSE.

bare

Should algorithm only continue for bare lists? Defaults to TRUE. See rlang::`bare-type-predicates`

...

Additional arguments to pass to predicate.

Details

The input is recursively evaluated to find elements that satisfy predicate, and only proceeds where rlang::is_list when argument bare is FALSE, and rlang::is_bare_list when it is TRUE.

Value

  • depths() returns an integer vector indicating the levels that contain elements satisfying the predicate.

  • depths_string() returns a character representation of the traversal. Brackets {} are used to indicate the level of the tree, commas to separate element-indices within a level, and the sign of the index to indicate whether the element satisfied predicate (- = yes, + = no).

Author

Alex Zajichek

Examples

#Find depths of data frames
df1 <-
  heart_disease %>%
  
    #Divide the frame into a list
    divide(
      Sex,
      HeartDisease,
      ChestPain
    )

df1 %>%
  
  #Get depths as an integer
  depths(
    predicate = is.data.frame
  )
#> [1] 3

df1 %>%

  #Get full structure
  depths_string(
    predicate = is.data.frame
  )
#> [1] "{1{1{-1,-2,-3,-4},2{-1,-2,-3}},2{1{-1,-2,-3,-4},2{-1,-2,-3,-4}}}"

#Shallower list
df2 <-
  heart_disease %>%
    divide(
      Sex,
      HeartDisease,
      ChestPain,
      depth = 1
    ) 

df2 %>%
  depths(
    predicate = is.data.frame
  )
#> [1] 1

df2 %>%
  depths_string(
    predicate = is.data.frame
  )
#> [1] "{-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15}"

#Allow for non-bare lists to be traversed
df1 %>%
  depths(
    predicate = is.factor,
    bare = FALSE
  )
#> [1] 4

#Make uneven list with diverse objects
my_list <-
  list(
    heart_disease,
    list(
      heart_disease
    ),
    1:10,
    list(
      heart_disease$Age,
      list(
        heart_disease
      )
    ),
    glm(
      formula = HeartDisease ~ .,
      data = heart_disease,
      family = "binomial"
    )
  )

#Find the data frames
my_list %>%
  depths(
    predicate = is.data.frame
  )
#> [1] 1 2 3

my_list %>%
  depths_string(
    predicate = is.data.frame
  )
#> [1] "{-1,2{-1},3,4{1,2{-1}},5}"

#Go deeper by relaxing bare list argument
my_list %>%
  depths_string(
    predicate = is.data.frame,
    bare = FALSE
  )
#> [1] "{-1{1,2,3,4,5,6,7,8,9},2{-1{1,2,3,4,5,6,7,8,9}},3,4{1,2{-1{1,2,3,4,5,6,7,8,9}}},5{1,2,3,4,5,6,7{1,2,3,4,5},8{1,2,3,4,5,6,7,8,9,10,11,12},9,10,11,12,13,14,15,16,17,18,19,20,-21{1,2,3,4,5,6,7,8,9},22,23,24,-25{1,2,3,4,5,6,7,8,9},26,27{1,2,3},28,29{1,2,3,4},30{1,2,3}}}"