• Stars
    star
    43
  • Rank 645,449 (Top 13 %)
  • Language
    R
  • License
    Other
  • Created about 5 years ago
  • Updated almost 2 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Unpacking, Interrogating and Subsetting R packages

foreman

Lifecycle: experimental

The goals of foreman are to:

  • Unpack a package’s functions to interrogate relationships of the functions within it.
  • Isolate function scripts within a package (including the documentation for local paths)
  • Consolidate a subset of self contained functions in a file(s) to allow for focused learning on a specific package functionality.

Given these goals it is important to state that this package is not meant to replace any parent package.

The package supports both local packages and compiled libraries.

Installation

remotes::install_github("yonicd/foreman")

Local Packages

This example will use a local fork of purrr.

library(foreman)
library(ggraph)
library(igraph)

Unpacking

Unpack a pacakge into a list

x <- unpack(path = '../forks/purrr/R', warn = FALSE)

Click the triangle to view the contents found in arrays.R

details::details(lapply(x$arrays.R,get_text),summary = 'arrays.R')
arrays.R
$array_branch
 [1] "#' Coerce array to list"                                              
 [2] "#'"                                                                   
 [3] "#' `array_branch()` and `array_tree()` enable arrays to be"           
 [4] "#' used with purrr's functionals by turning them into lists. The"     
 [5] "#' details of the coercion are controlled by the `margin`"            
 [6] "#' argument. `array_tree()` creates an hierarchical list (a tree)"    
 [7] "#' that has as many levels as dimensions specified in `margin`,"      
 [8] "#' while `array_branch()` creates a flat list (by analogy, a"         
 [9] "#' branch) along all mentioned dimensions."                           
[10] "#'"                                                                   
[11] "#' When no margin is specified, all dimensions are used by"           
[12] "#' default. When `margin` is a numeric vector of length zero, the"    
[13] "#' whole array is wrapped in a list."                                 
[14] "#' @param array An array to coerce into a list."                      
[15] "#' @param margin A numeric vector indicating the positions of the"    
[16] "#'   indices to be to be enlisted. If `NULL`, a full margin is"       
[17] "#'   used. If `numeric(0)`, the array as a whole is wrapped in a"     
[18] "#'   list."                                                           
[19] "#' @name array-coercion"                                              
[20] "#' @export"                                                           
[21] "#' @examples"                                                         
[22] "#' # We create an array with 3 dimensions"                            
[23] "#' x <- array(1:12, c(2, 2, 3))"                                      
[24] "#'"                                                                   
[25] "#' # A full margin for such an array would be the vector 1:3. This is"
[26] "#' # the default if you don't specify a margin"                       
[27] "#'"                                                                   
[28] "#' # Creating a branch along the full margin is equivalent to"        
[29] "#' # as.list(array) and produces a list of size length(x):"           
[30] "#' array_branch(x) %>% str()"                                         
[31] "#'"                                                                   
[32] "#' # A branch along the first dimension yields a list of length 2"    
[33] "#' # with each element containing a 2x3 array:"                       
[34] "#' array_branch(x, 1) %>% str()"                                      
[35] "#'"                                                                   
[36] "#' # A branch along the first and third dimensions yields a list of"  
[37] "#' # length 2x3 whose elements contain a vector of length 2:"         
[38] "#' array_branch(x, c(1, 3)) %>% str()"                                
[39] "#'"                                                                   
[40] "#' # Creating a tree from the full margin creates a list of lists of" 
[41] "#' # lists:"                                                          
[42] "#' array_tree(x) %>% str()"                                           
[43] "#'"                                                                   
[44] "#' # The ordering and the depth of the tree are controlled by the"    
[45] "#' # margin argument:"                                                
[46] "#' array_tree(x, c(3, 1)) %>% str()"                                  
[47] "array_branch <- function(array, margin = NULL) {"                     
[48] "  dims <- dim(array) %||% length(array)"                              
[49] "  margin <- margin %||% seq_along(dims)"                              
[50] ""                                                                     
[51] "  if (length(margin) == 0) {"                                         
[52] "    list(array)"                                                      
[53] "  } else if (is.null(dim(array))) {"                                  
[54] "    if (!identical(as.integer(margin), 1L)) {"                        
[55] "      abort(sprintf("                                                 
[56] "        \"`margin` must be `NULL` or `1` with 1D arrays, not `%s`\"," 
[57] "        toString(margin)"                                             
[58] "      ))"                                                             
[59] "    }"                                                                
[60] "    as.list(array)"                                                   
[61] "  } else {"                                                           
[62] "    flatten(apply(array, margin, list))"                              
[63] "  }"                                                                  
[64] "}"                                                                    

$array_tree
 [1] "#' @rdname array-coercion"                                                     
 [2] "#' @export"                                                                    
 [3] "array_tree <- function(array, margin = NULL) {"                                
 [4] "  dims <- dim(array) %||% length(array)"                                       
 [5] "  margin <- margin %||% seq_along(dims)"                                       
 [6] ""                                                                              
 [7] "  if (length(margin) > 1) {"                                                   
 [8] "    new_margin <- ifelse(margin[-1] > margin[[1]], margin[-1] - 1, margin[-1])"
 [9] "    apply(array, margin[[1]], array_tree, new_margin)"                         
[10] "  } else {"                                                                    
[11] "    array_branch(array, margin)"                                               
[12] "  }"                                                                           
[13] "}"                                                                             

Relationships

x_rel <- relationship(x)

Relationships contained in arrays.R

x_rel$arrays.R
#> $array_branch
#> [1] "flatten"
#> 
#> $array_tree
#> [1] "array_branch"

Functions that compose calls

relationship(x,parent = 'compose')
#> $compose.R
#> $compose.R$compose
#> [1] "compose" "map"     "fn"     
#> 
#> 
#> attr(,"class")
#> [1] "relationship" "list"

Functions who call flatten

relationship(x,child = 'flatten')
#> $arrays.R
#> $arrays.R$array_branch
#> [1] "flatten"
#> 
#> 
#> $lmap.R
#> $lmap.R$lmap_at
#> [1] "flatten"
#> 
#> 
#> $splice.R
#> $splice.R$splice_if
#> [1] "flatten"
#> 
#> 
#> attr(,"class")
#> [1] "relationship" "list"

Convert relationships to a data.frame

x_rel_df <- as.data.frame(x_rel)

Click the triangle to view the data.frame

details::details(x_rel_df,summary = 'Relatives')
Relatives
                           child                 parent               file
1                        flatten           array_branch           arrays.R
2                      as_mapper            as_function        as_mapper.R
3                   stop_defunct            as_function        as_mapper.R
4                     paste_line            as_function        as_mapper.R
5                         coerce             coerce_lgl           coerce.R
6                   can_simplify              as_vector         coercion.R
7                warn_deprecated signal_soft_deprecated compat-lifecycle.R
8                        compose                compose          compose.R
9                            map                compose          compose.R
10                            fn                compose          compose.R
11                     as_vector                lift_vl      composition.R
12               what_bad_object          stop_bad_type       conditions.R
13              friendly_type_of          stop_bad_type       conditions.R
14                     as_mapper                  cross            cross.R
15 as_predicate_friendly_type_of                  cross            cross.R
16                       compact                  cross            cross.R
17                       is_bool                  cross            cross.R
18                       map_int              vec_depth            depth.R
19                  as_predicate                 detect           detect.R
20                         index                 detect           detect.R
21                  as_predicate                  every       every-some.R
22                  detect_index             head_while        head-tail.R
23                        negate             head_while        head-tail.R
24                     as_mapper                   imap             imap.R
25                     vec_index                   imap             imap.R
26                          map2                   imap             imap.R
27                         probe                   keep             keep.R
28                  list_recurse            list_modify      list-modify.R
29                       lmap_at                   lmap             lmap.R
30                     as_mapper                    map              map.R
31                     as_mapper                   map2        map2-pmap.R
32                     as_mapper         modify.default           modify.R
33                     as_mapper                 negate           negate.R
34                     as_mapper                 safely           output.R
35                 capture_error                 safely           output.R
36        signal_soft_deprecated                partial          partial.R
37                  stop_defunct                partial          partial.R
38                           map                partial          partial.R
39                    paste_line                partial          partial.R
40              friendly_type_of                partial          partial.R
41                     assign_in              `pluck<-`            pluck.R
42                     as_mapper            insistently             rate.R
43                 stop_bad_type            insistently             rate.R
44                 capture_error            insistently             rate.R
45                  rate_backoff            insistently             rate.R
46                       is_rate            insistently             rate.R
47                    rate_sleep            insistently             rate.R
48                    rate_reset            insistently             rate.R
49                             f            insistently             rate.R
50                   reduce_impl                 reduce           reduce.R
51                     eval_dots                  rerun            rerun.R
52                     has_names                  rerun            rerun.R
53                          map2             invoke_map   retired-invoke.R
54            as_invoke_function             invoke_map   retired-invoke.R
55                     splice_if                 splice           splice.R
56                  check_tibble    maybe_as_data_frame            utils.R

Plotting the relationships

graph <- igraph::graph_from_data_frame(x_rel_df,directed = TRUE)
igraph::V(graph)$parents <- names(igraph::V(graph))
ggraph(graph) +
  geom_edge_link(
    aes(colour = file),
    arrow = grid::arrow(length = unit(0.05, "inches"))) +
  geom_node_text(aes(label = parents),size = 3) +
  labs(title = 'purrr function map', colour = 'Exported') + 
  ggplot2::theme(legend.position   = 'bottom')
#> Using `nicely` as default layout

Subset

Subsetting Package Functions

sub_x <- subset(x,'compose')

Click the triangle to view the contents found in the subset containing compose and the functions the it calls.

details::details(lapply(sub_x,get_text),summary = 'Package subset')
Package subset
$compose.R
 [1] "#' Compose multiple functions"                                           
 [2] "#'"                                                                      
 [3] "#' @param ... Functions to apply in order (from right to left by"        
 [4] "#'   default). Formulas are converted to functions in the usual way."    
 [5] "#'"                                                                      
 [6] "#'   These dots support [tidy dots][rlang::list2] features. In"          
 [7] "#'   particular, if your functions are stored in a list, you can"        
 [8] "#'   splice that in with `!!!`."                                         
 [9] "#' @param .dir If `\"backward\"` (the default), the functions are called"
[10] "#'   in the reverse order, from right to left, as is conventional in"    
[11] "#'   mathematics. If `\"forward\"`, they are called from left to right." 
[12] "#' @return A function"                                                   
[13] "#' @export"                                                              
[14] "#' @examples"                                                            
[15] "#' not_null <- compose(`!`, is.null)"                                    
[16] "#' not_null(4)"                                                          
[17] "#' not_null(NULL)"                                                       
[18] "#'"                                                                      
[19] "#' add1 <- function(x) x + 1"                                            
[20] "#' compose(add1, add1)(8)"                                               
[21] "#'"                                                                      
[22] "#' # You can use the formula shortcut for functions:"                    
[23] "#' fn <- compose(~ paste(.x, \"foo\"), ~ paste(.x, \"bar\"))"            
[24] "#' fn(\"input\")"                                                        
[25] "#'"                                                                      
[26] "#' # Lists of functions can be spliced with !!!"                         
[27] "#' fns <- list("                                                         
[28] "#'   function(x) paste(x, \"foo\"),"                                     
[29] "#'   ~ paste(.x, \"bar\")"                                               
[30] "#' )"                                                                    
[31] "#' fn <- compose(!!!fns)"                                                
[32] "#' fn(\"input\")"                                                        
[33] "compose <- function(..., .dir = c(\"backward\", \"forward\")) {"         
[34] "  .dir <- arg_match(.dir, c(\"backward\", \"forward\"))"                 
[35] ""                                                                        
[36] "  fns <- map(list2(...), rlang::as_closure, env = caller_env())"         
[37] "  if (!length(fns)) {"                                                   
[38] "    # Return the identity function"                                      
[39] "    return(compose(function(x, ...) x))"                                 
[40] "  }"                                                                     
[41] ""                                                                        
[42] "  if (.dir == \"backward\") {"                                           
[43] "    n <- length(fns)"                                                    
[44] "    first_fn <- fns[[n]]"                                                
[45] "    fns <- rev(fns[-n])"                                                 
[46] "  } else {"                                                              
[47] "    first_fn <- fns[[1]]"                                                
[48] "    fns <- fns[-1]"                                                      
[49] "  }"                                                                     
[50] ""                                                                        
[51] "  body <- expr({"                                                        
[52] "    out <- !!fn_body(first_fn)"                                          
[53] ""                                                                        
[54] "    fns <- !!fns"                                                        
[55] "    for (fn in fns) {"                                                   
[56] "      out <- fn(out)"                                                    
[57] "    }"                                                                   
[58] ""                                                                        
[59] "    out"                                                                 
[60] "  })"                                                                    
[61] ""                                                                        
[62] "  structure("                                                            
[63] "    new_function(formals(first_fn), body, fn_env(first_fn)),"            
[64] "    class = c(\"purrr_function_compose\", \"function\"),"                
[65] "    first_fn = first_fn,"                                                
[66] "    fns = fns"                                                           
[67] "  )"                                                                     
[68] "}"                                                                       

$map.R
  [1] "#' Apply a function to each element of a vector"                              
  [2] "#'"                                                                           
  [3] "#' @description"                                                              
  [4] "#'"                                                                           
  [5] "#' The map functions transform their input by applying a function to"         
  [6] "#' each element and returning a vector the same length as the input."         
  [7] "#'"                                                                           
  [8] "#' * `map()`, `map_if()` and `map_at()` always return a list. See the"        
  [9] "#'   [modify()] family for versions that return an object of the same"        
 [10] "#'   type as the input."                                                      
 [11] "#'"                                                                           
 [12] "#'   The `_if` and `_at` variants take a predicate function `.p` that"        
 [13] "#'   determines which elements of `.x` are transformed with `.f`."            
 [14] "#'"                                                                           
 [15] "#' * `map_lgl()`, `map_int()`, `map_dbl()` and `map_chr()` each return"       
 [16] "#'    an atomic vector of the indicated type (or die trying)."                
 [17] "#'"                                                                           
 [18] "#'    The return value of `.f` must be of length one for each element of"     
 [19] "#'    `.x`. If `.f` uses an extractor function shortcut, `.default`"          
 [20] "#'    can be specified to handle values that are absent or empty.  See"       
 [21] "#'    [as_mapper()] for more on `.default`."                                  
 [22] "#'"                                                                           
 [23] "#' * `map_dfr()` and `map_dfc()` return data frames created by"               
 [24] "#'   row-binding and column-binding respectively. They require dplyr"         
 [25] "#'   to be installed."                                                        
 [26] "#'"                                                                           
 [27] "#' * `walk()` calls `.f` for its side-effect and returns the input `.x`."     
 [28] "#'"                                                                           
 [29] "#' @inheritParams as_mapper"                                                  
 [30] "#' @param .x A list or atomic vector."                                        
 [31] "#' @param .p A single predicate function, a formula describing such a"        
 [32] "#'   predicate function, or a logical vector of the same length as `.x`."     
 [33] "#'   Alternatively, if the elements of `.x` are themselves lists of"          
 [34] "#'   objects, a string indicating the name of a logical element in the"       
 [35] "#'   inner lists. Only those elements where `.p` evaluates to"                
 [36] "#'   `TRUE` will be modified."                                                
 [37] "#' @param .at A character vector of names, positive numeric vector of"        
 [38] "#'   positions to include, or a negative numeric vector of positions to"      
 [39] "#'   exlude. Only those elements corresponding to `.at` will be modified."    
 [40] "#' @param ... Additional arguments passed on to the mapped function."         
 [41] "#' @return All functions return a vector the same length as `.x`."            
 [42] "#'"                                                                           
 [43] "#'   `map()` returns a list, `map_lgl()` a logical vector, `map_int()` an"    
 [44] "#'   integer vector, `map_dbl()` a double vector, and `map_chr()` a character"
 [45] "#'   vector. The output of `.f` will be automatically typed upwards,"         
 [46] "#'   e.g. logical -> integer -> double -> character."                         
 [47] "#'"                                                                           
 [48] "#'   If `.x` has `names()`, the return value preserves those names."          
 [49] "#'"                                                                           
 [50] "#'   `walk()` returns the input `.x` (invisibly). This makes it easy to"      
 [51] "#'   use in pipe."                                                            
 [52] "#' @export"                                                                   
 [53] "#' @family map variants"                                                      
 [54] "#' @examples"                                                                 
 [55] "#' 1:10 %>%"                                                                  
 [56] "#'   map(rnorm, n = 10) %>%"                                                  
 [57] "#'   map_dbl(mean)"                                                           
 [58] "#'"                                                                           
 [59] "#' # Or use an anonymous function"                                            
 [60] "#' 1:10 %>%"                                                                  
 [61] "#'   map(function(x) rnorm(10, x))"                                           
 [62] "#'"                                                                           
 [63] "#' # Or a formula"                                                            
 [64] "#' 1:10 %>%"                                                                  
 [65] "#'   map(~ rnorm(10, .x))"                                                    
 [66] "#'"                                                                           
 [67] "#' # The names of the input are preserved in the output:"                     
 [68] "#' list(foo = 1, bar = 2) %>% map(`+`, 10)"                                   
 [69] "#'"                                                                           
 [70] "#' # Using set_names() with character vectors is handy to keep track"         
 [71] "#' # of the original inputs:"                                                 
 [72] "#' set_names(c(\"foo\", \"bar\")) %>% map_chr(paste0, \":suffix\")"           
 [73] "#'"                                                                           
 [74] "#' # Extract by name or position"                                             
 [75] "#' # .default specifies value for elements that are missing or NULL"          
 [76] "#' l1 <- list(list(a = 1L), list(a = NULL, b = 2L), list(b = 3L))"            
 [77] "#' l1 %>% map(\"a\", .default = \"???\")"                                     
 [78] "#' l1 %>% map_int(\"b\", .default = NA)"                                      
 [79] "#' l1 %>% map_int(2, .default = NA)"                                          
 [80] "#'"                                                                           
 [81] "#' # Supply multiple values to index deeply into a list"                      
 [82] "#' l2 <- list("                                                               
 [83] "#'   list(num = 1:3,     letters[1:3]),"                                      
 [84] "#'   list(num = 101:103, letters[4:6]),"                                      
 [85] "#'   list()"                                                                  
 [86] "#' )"                                                                         
 [87] "#' l2 %>% map(c(2, 2))"                                                       
 [88] "#'"                                                                           
 [89] "#' # Use a list to build an extractor that mixes numeric indices and names,"  
 [90] "#' # and .default to provide a default value if the element does not exist"   
 [91] "#' l2 %>% map(list(\"num\", 3))"                                              
 [92] "#' l2 %>% map_int(list(\"num\", 3), .default = NA)"                           
 [93] "#'"                                                                           
 [94] "#'"                                                                           
 [95] "#' # Use a predicate function to decide whether to map a function:"           
 [96] "#' map_if(iris, is.factor, as.character)"                                     
 [97] "#'"                                                                           
 [98] "#' # Specify an alternative with the `.else` argument:"                       
 [99] "#' map_if(iris, is.factor, as.character, .else = as.integer)"                 
[100] "#'"                                                                           
[101] "#' # A more realistic example: split a data frame into pieces, fit a"         
[102] "#' # model to each piece, summarise and extract R^2"                          
[103] "#' mtcars %>%"                                                                
[104] "#'   split(.$cyl) %>%"                                                        
[105] "#'   map(~ lm(mpg ~ wt, data = .x)) %>%"                                      
[106] "#'   map(summary) %>%"                                                        
[107] "#'   map_dbl(\"r.squared\")"                                                  
[108] "#'"                                                                           
[109] "#' # Use map_lgl(), map_dbl(), etc to reduce to a vector."                    
[110] "#' # * list"                                                                  
[111] "#' mtcars %>% map(sum)"                                                       
[112] "#' # * vector"                                                                
[113] "#' mtcars %>% map_dbl(sum)"                                                   
[114] "#'"                                                                           
[115] "#' # If each element of the output is a data frame, use"                      
[116] "#' # map_dfr to row-bind them together:"                                      
[117] "#' mtcars %>%"                                                                
[118] "#'   split(.$cyl) %>%"                                                        
[119] "#'   map(~ lm(mpg ~ wt, data = .x)) %>%"                                      
[120] "#'   map_dfr(~ as.data.frame(t(as.matrix(coef(.)))))"                         
[121] "#' # (if you also want to preserve the variable names see"                    
[122] "#' # the broom package)"                                                      
[123] "#'"                                                                           
[124] "#' # Use `map_depth()` to recursively traverse nested vectors and map"        
[125] "#' # a function at a certain depth:"                                          
[126] "#' x <- list(a = list(foo = 1:2, bar = 3:4), b = list(baz = 5:6))"            
[127] "#' str(x)"                                                                    
[128] "#' map_depth(x, 2, paste, collapse = \"/\")"                                  
[129] "#'"                                                                           
[130] "#' # Equivalent to:"                                                          
[131] "#' map(x, map, paste, collapse = \"/\")"                                      
[132] "map <- function(.x, .f, ...) {"                                               
[133] "  .f <- as_mapper(.f, ...)"                                                   
[134] "  .Call(map_impl, environment(), \".x\", \".f\", \"list\")"                   
[135] "}"                                                                            

$reduce.R
[1] "    fn <- function(x, y, ...) .f(y, x, ...)"

Consolidation

Consolidating Subsetted Functions into a File

pack_path <- repack(sub_x)
#> Functions packed to /var/folders/kx/t4h_mm1910sb7vhm_gnfnx2c0000gn/T//Rtmpgg7cm0/foreman/unpacked.R

Click the triangle to view the contents found in the file containing the consolidated functions.

details::details(file.path(pack_path,'unpacked.R'),summary = 'Consolidated Script')
Consolidated Script
#Generated by foreman:

#' Compose multiple functions
#'
#' @param ... Functions to apply in order (from right to left by
#'   default). Formulas are converted to functions in the usual way.
#'
#'   These dots support [tidy dots][rlang::list2] features. In
#'   particular, if your functions are stored in a list, you can
#'   splice that in with `!!!`.
#' @param .dir If `"backward"` (the default), the functions are called
#'   in the reverse order, from right to left, as is conventional in
#'   mathematics. If `"forward"`, they are called from left to right.
#' @return A function
#' @export
#' @examples
#' not_null <- compose(`!`, is.null)
#' not_null(4)
#' not_null(NULL)
#'
#' add1 <- function(x) x + 1
#' compose(add1, add1)(8)
#'
#' # You can use the formula shortcut for functions:
#' fn <- compose(~ paste(.x, "foo"), ~ paste(.x, "bar"))
#' fn("input")
#'
#' # Lists of functions can be spliced with !!!
#' fns <- list(
#'   function(x) paste(x, "foo"),
#'   ~ paste(.x, "bar")
#' )
#' fn <- compose(!!!fns)
#' fn("input")
compose <- function(..., .dir = c("backward", "forward")) {
  .dir <- arg_match(.dir, c("backward", "forward"))

  fns <- map(list2(...), rlang::as_closure, env = caller_env())
  if (!length(fns)) {
    # Return the identity function
    return(compose(function(x, ...) x))
  }

  if (.dir == "backward") {
    n <- length(fns)
    first_fn <- fns[[n]]
    fns <- rev(fns[-n])
  } else {
    first_fn <- fns[[1]]
    fns <- fns[-1]
  }

  body <- expr({
    out <- !!fn_body(first_fn)

    fns <- !!fns
    for (fn in fns) {
      out <- fn(out)
    }

    out
  })

  structure(
    new_function(formals(first_fn), body, fn_env(first_fn)),
    class = c("purrr_function_compose", "function"),
    first_fn = first_fn,
    fns = fns
  )
}
#' Apply a function to each element of a vector
#'
#' @description
#'
#' The map functions transform their input by applying a function to
#' each element and returning a vector the same length as the input.
#'
#' * `map()`, `map_if()` and `map_at()` always return a list. See the
#'   [modify()] family for versions that return an object of the same
#'   type as the input.
#'
#'   The `_if` and `_at` variants take a predicate function `.p` that
#'   determines which elements of `.x` are transformed with `.f`.
#'
#' * `map_lgl()`, `map_int()`, `map_dbl()` and `map_chr()` each return
#'    an atomic vector of the indicated type (or die trying).
#'
#'    The return value of `.f` must be of length one for each element of
#'    `.x`. If `.f` uses an extractor function shortcut, `.default`
#'    can be specified to handle values that are absent or empty.  See
#'    [as_mapper()] for more on `.default`.
#'
#' * `map_dfr()` and `map_dfc()` return data frames created by
#'   row-binding and column-binding respectively. They require dplyr
#'   to be installed.
#'
#' * `walk()` calls `.f` for its side-effect and returns the input `.x`.
#'
#' @inheritParams as_mapper
#' @param .x A list or atomic vector.
#' @param .p A single predicate function, a formula describing such a
#'   predicate function, or a logical vector of the same length as `.x`.
#'   Alternatively, if the elements of `.x` are themselves lists of
#'   objects, a string indicating the name of a logical element in the
#'   inner lists. Only those elements where `.p` evaluates to
#'   `TRUE` will be modified.
#' @param .at A character vector of names, positive numeric vector of
#'   positions to include, or a negative numeric vector of positions to
#'   exlude. Only those elements corresponding to `.at` will be modified.
#' @param ... Additional arguments passed on to the mapped function.
#' @return All functions return a vector the same length as `.x`.
#'
#'   `map()` returns a list, `map_lgl()` a logical vector, `map_int()` an
#'   integer vector, `map_dbl()` a double vector, and `map_chr()` a character
#'   vector. The output of `.f` will be automatically typed upwards,
#'   e.g. logical -> integer -> double -> character.
#'
#'   If `.x` has `names()`, the return value preserves those names.
#'
#'   `walk()` returns the input `.x` (invisibly). This makes it easy to
#'   use in pipe.
#' @export
#' @family map variants
#' @examples
#' 1:10 %>%
#'   map(rnorm, n = 10) %>%
#'   map_dbl(mean)
#'
#' # Or use an anonymous function
#' 1:10 %>%
#'   map(function(x) rnorm(10, x))
#'
#' # Or a formula
#' 1:10 %>%
#'   map(~ rnorm(10, .x))
#'
#' # The names of the input are preserved in the output:
#' list(foo = 1, bar = 2) %>% map(`+`, 10)
#'
#' # Using set_names() with character vectors is handy to keep track
#' # of the original inputs:
#' set_names(c("foo", "bar")) %>% map_chr(paste0, ":suffix")
#'
#' # Extract by name or position
#' # .default specifies value for elements that are missing or NULL
#' l1 <- list(list(a = 1L), list(a = NULL, b = 2L), list(b = 3L))
#' l1 %>% map("a", .default = "???")
#' l1 %>% map_int("b", .default = NA)
#' l1 %>% map_int(2, .default = NA)
#'
#' # Supply multiple values to index deeply into a list
#' l2 <- list(
#'   list(num = 1:3,     letters[1:3]),
#'   list(num = 101:103, letters[4:6]),
#'   list()
#' )
#' l2 %>% map(c(2, 2))
#'
#' # Use a list to build an extractor that mixes numeric indices and names,
#' # and .default to provide a default value if the element does not exist
#' l2 %>% map(list("num", 3))
#' l2 %>% map_int(list("num", 3), .default = NA)
#'
#'
#' # Use a predicate function to decide whether to map a function:
#' map_if(iris, is.factor, as.character)
#'
#' # Specify an alternative with the `.else` argument:
#' map_if(iris, is.factor, as.character, .else = as.integer)
#'
#' # A more realistic example: split a data frame into pieces, fit a
#' # model to each piece, summarise and extract R^2
#' mtcars %>%
#'   split(.$cyl) %>%
#'   map(~ lm(mpg ~ wt, data = .x)) %>%
#'   map(summary) %>%
#'   map_dbl("r.squared")
#'
#' # Use map_lgl(), map_dbl(), etc to reduce to a vector.
#' # * list
#' mtcars %>% map(sum)
#' # * vector
#' mtcars %>% map_dbl(sum)
#'
#' # If each element of the output is a data frame, use
#' # map_dfr to row-bind them together:
#' mtcars %>%
#'   split(.$cyl) %>%
#'   map(~ lm(mpg ~ wt, data = .x)) %>%
#'   map_dfr(~ as.data.frame(t(as.matrix(coef(.)))))
#' # (if you also want to preserve the variable names see
#' # the broom package)
#'
#' # Use `map_depth()` to recursively traverse nested vectors and map
#' # a function at a certain depth:
#' x <- list(a = list(foo = 1:2, bar = 3:4), b = list(baz = 5:6))
#' str(x)
#' map_depth(x, 2, paste, collapse = "/")
#'
#' # Equivalent to:
#' map(x, map, paste, collapse = "/")
map <- function(.x, .f, ...) {
  .f <- as_mapper(.f, ...)
  .Call(map_impl, environment(), ".x", ".f", "list")
}
    fn <- function(x, y, ...) .f(y, x, ...)

Compiled Library

This example will use the installed library future.

Using foreman with an compiled libraries is also simple

library(future)
#> 
#> Attaching package: 'future'
#> The following objects are masked from 'package:igraph':
#> 
#>     %->%, %<-%

unpacked_future <- unpack(ns = 'future')%>%
  relationship()%>%
  as.data.frame()
graph <- igraph::graph_from_data_frame(unpacked_future,directed = TRUE)
igraph::V(graph)$parents <- names(igraph::V(graph))
igraph::V(graph)$exported <- names(igraph::V(graph))%in%ls('package:future')
ggraph(graph) +
  geom_edge_link(
    arrow = grid::arrow(length = unit(0.05, "inches")),alpha = 0.05) +
  geom_node_text(aes(colour = exported,label = parents),size = 2) +
  labs(title = 'future function map', colour = 'Exported') + 
  ggplot2::theme(legend.position   = 'bottom')
#> Using `nicely` as default layout

More Repositories

1

ggedit

Interactively edit ggplot layer aesthetics and theme definitions
HTML
239
star
2

carbonate

carbon.js for R
R
208
star
3

sinew

Generate roxygen2 skeletons populated with information scraped from the function script.
R
162
star
4

slickR

slick carousel htmlwidget for R
JavaScript
151
star
5

d3Tree

htmlwidget that binds d3js collapsible trees to R and Shiny to make an interactive search tool
R
86
star
6

details

R Package to Create Details HTML Tag for Markdown and Package Documentation
R
84
star
7

bplyr

basic dplyr and tidyr functionality without the tidyverse dependencies
R
83
star
8

reactor

unit testing for shiny reactivity
R
57
star
9

covrpage

Create a summary readme for the testthat subdirectory to communicate with potential users
R
50
star
10

texPreview

Efficiently iterate, refine and share snippets of LaTeX in R with ease
R
49
star
11

shinyHeatmaply

R
47
star
12

whereami

Reliably return location where command is called from in R.
HTML
41
star
13

rpdf

pdf.js htmlwidget for R
JavaScript
38
star
14

slackreprex

reprex + slack
R
31
star
15

rsam

RStudio Addin Manager
R
31
star
16

Elections

Real time tracker and analysis of 2016 USA Elections
R
31
star
17

jsTree

R htmlwidget for inspecting heirachal structures with the β€˜jQuery’ β€˜jsTree’ Plugin.
HTML
29
star
18

shinyCanvas

R
22
star
19

carbonace

convert ace editor as high resolution images to share
R
22
star
20

shredder

API for exploring and iterating rstan fit objects
R
21
star
21

slackteams

Manage and Interact with multiple Slack teams in R
R
21
star
22

regexSelect

Enable regular expression searching of selectize object options in the R Shiny package
R
19
star
23

snapper

snap images of html objects using only JavaScript in shiny apps
R
18
star
24

texblocks

WIP: tex table building blocks
R
12
star
25

shinyselect

Observe Multiple Reactive Elements using tidyselect-like verbs
R
12
star
26

vcs

Remote repository file querying, structure inspection, script sourcing directly from R
R
11
star
27

places

Reliably store, manage and verify multiple file paths of a project using a simple and consistent API.
R
10
star
28

shinycarbon

shiny wrapper for carbonate R package
R
10
star
29

supermarketprices

read daily suprmarket data in all israel stores
HTML
10
star
30

tidycheckUsage

create tidy output for codetools::checkUsage functions
R
9
star
31

ripe

rerun {magrittr} pipelines
R
9
star
32

gunflow

R
9
star
33

tidylog.addin

rstudio addin for tidylog package
R
9
star
34

issue

Create a simple markdown table to display current issue status of the repo
R
8
star
35

slackthreads

Wrangle slack conversations, replies and threads in R
R
6
star
36

shinyProf

R
6
star
37

slackr-app

Slack Incoming Webhook for slackr R package
6
star
38

revisionist

conservative version R package installation
R
6
star
39

gha_r_tutorial

Short tutorial for using GitHub Actions and R
CSS
6
star
40

slackcalls

generic package to call slack api from R
R
5
star
41

craninfo

sessioninfo with cran check information
R
5
star
42

helpdesk

Query URL links embedded in Installed Packages
R
5
star
43

glossaries

glossary functionality for Rmarkdown documents
HTML
5
star
44

shinycovr

R
5
star
45

chunky

RStudio addin to wrap script in Rmarkdown chunks
R
5
star
46

ciderhouse

R
4
star
47

ghnet

Github Commit Data + ggraph networks plots
R
4
star
48

puzzlemath

R Shiny App game for Learning Math
R
4
star
49

shield

R
3
star
50

blog

my blog
HTML
3
star
51

hex

project hex stickers
R
3
star
52

slackblocks

Slack Blocks in R
R
3
star
53

captions

R
2
star
54

tidyghql

create tidy outputs of open github issues and prs using graphql
2
star
55

CIMDO

Shiny Dashboard for IMF CIMDO Results
R
2
star
56

potus_public_schedule

script and shinyapp to cross reference potus schedule and tweets
R
2
star
57

slackposts

Interact with chats and files methods of Slack API in R
R
2
star
58

lmmen

R package that solves the linear mixed model elastic net
R
2
star
59

toddlr

toddler in chief R package/Shiny App
R
1
star
60

shinyVE

Shiny App to Visualize FDA Vaccinne Effect Guidelines
R
1
star
61

sinew_presentation

Sinew R Package Presentation
HTML
1
star
62

streamline

NONMEM control streams managment in R
R
1
star
63

SearchTree

Active shiny filter of complex data structures using d3 trees
JavaScript
1
star
64

paperpile

TeX
1
star
65

texsnippets

Common boilerplate TeX commands as RStudio snippets
R
1
star
66

pkgr.utils

R
1
star
67

rtravis

R
1
star
68

basecamper

Interact with basecamp api in R
R
1
star