EVOLUTION-MANAGER
Edit File: modify.html
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><title>R: Modify elements selectively</title> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rel="stylesheet" type="text/css" href="R.css" /> </head><body> <table width="100%" summary="page for modify {purrr}"><tr><td>modify {purrr}</td><td style="text-align: right;">R Documentation</td></tr></table> <h2>Modify elements selectively</h2> <h3>Description</h3> <p>Unlike <code><a href="map.html">map()</a></code> and its variants which always return a fixed object type (list for <code>map()</code>, integer vector for <code>map_int()</code>, etc), the <code>modify()</code> family always returns the same type as the input object. </p> <ul> <li> <p><code>modify()</code> is a shortcut for <code style="white-space: pre;">x[[i]] <- f(x[[i]]); return(x)</code>. </p> </li> <li> <p><code>modify_if()</code> only modifies the elements of <code>x</code> that satisfy a predicate and leaves the others unchanged. <code>modify_at()</code> only modifies elements given by names or positions. </p> </li> <li> <p><code>modify2()</code> modifies the elements of <code>.x</code> but also passes the elements of <code>.y</code> to <code>.f</code>, just like <code><a href="map2.html">map2()</a></code>. <code>imodify()</code> passes the names or the indices to <code>.f</code> like <code><a href="imap.html">imap()</a></code> does. </p> </li> <li> <p><code>modify_depth()</code> only modifies elements at a given level of a nested data structure. </p> </li> <li> <p><code><a href="modify_in.html">modify_in()</a></code> modifies a single element in a <code><a href="pluck.html">pluck()</a></code> location. </p> </li></ul> <h3>Usage</h3> <pre> modify(.x, .f, ...) ## Default S3 method: modify(.x, .f, ...) modify_if(.x, .p, .f, ..., .else = NULL) ## Default S3 method: modify_if(.x, .p, .f, ..., .else = NULL) modify_at(.x, .at, .f, ...) ## Default S3 method: modify_at(.x, .at, .f, ...) modify2(.x, .y, .f, ...) imodify(.x, .f, ...) modify_depth(.x, .depth, .f, ..., .ragged = .depth < 0) ## Default S3 method: modify_depth(.x, .depth, .f, ..., .ragged = .depth < 0) </pre> <h3>Arguments</h3> <table summary="R argblock"> <tr valign="top"><td><code>.x</code></td> <td> <p>A list or atomic vector.</p> </td></tr> <tr valign="top"><td><code>.f</code></td> <td> <p>A function, formula, or vector (not necessarily atomic). </p> <p>If a <strong>function</strong>, it is used as is. </p> <p>If a <strong>formula</strong>, e.g. <code>~ .x + 2</code>, it is converted to a function. There are three ways to refer to the arguments: </p> <ul> <li><p> For a single argument function, use <code>.</code> </p> </li> <li><p> For a two argument function, use <code>.x</code> and <code>.y</code> </p> </li> <li><p> For more arguments, use <code>..1</code>, <code>..2</code>, <code>..3</code> etc </p> </li></ul> <p>This syntax allows you to create very compact anonymous functions. </p> <p>If <strong>character vector</strong>, <strong>numeric vector</strong>, or <strong>list</strong>, it is converted to an extractor function. Character vectors index by name and numeric vectors index by position; use a list to index by position and name at different levels. If a component is not present, the value of <code>.default</code> will be returned.</p> </td></tr> <tr valign="top"><td><code>...</code></td> <td> <p>Additional arguments passed on to the mapped function.</p> </td></tr> <tr valign="top"><td><code>.p</code></td> <td> <p>A single predicate function, a formula describing such a predicate function, or a logical vector of the same length as <code>.x</code>. Alternatively, if the elements of <code>.x</code> are themselves lists of objects, a string indicating the name of a logical element in the inner lists. Only those elements where <code>.p</code> evaluates to <code>TRUE</code> will be modified.</p> </td></tr> <tr valign="top"><td><code>.else</code></td> <td> <p>A function applied to elements of <code>.x</code> for which <code>.p</code> returns <code>FALSE</code>.</p> </td></tr> <tr valign="top"><td><code>.at</code></td> <td> <p>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 <code>.at</code> will be modified. If the <code>tidyselect</code> package is installed, you can use <code>vars()</code> and the <code>tidyselect</code> helpers to select elements.</p> </td></tr> <tr valign="top"><td><code>.y</code></td> <td> <p>Vectors of the same length. A vector of length 1 will be recycled.</p> </td></tr> <tr valign="top"><td><code>.depth</code></td> <td> <p>Level of <code>.x</code> to map on. Use a negative value to count up from the lowest level of the list. </p> <ul> <li> <p><code>modify_depth(x, 0, fun)</code> is equivalent to <code>x[] <- fun(x)</code>. </p> </li> <li> <p><code>modify_depth(x, 1, fun)</code> is equivalent to <code>x <- modify(x, fun)</code> </p> </li> <li> <p><code>modify_depth(x, 2, fun)</code> is equivalent to <code>x <- modify(x, ~ modify(., fun))</code> </p> </li></ul> </td></tr> <tr valign="top"><td><code>.ragged</code></td> <td> <p>If <code>TRUE</code>, will apply to leaves, even if they're not at depth <code>.depth</code>. If <code>FALSE</code>, will throw an error if there are no elements at depth <code>.depth</code>.</p> </td></tr> </table> <h3>Details</h3> <p>Since the transformation can alter the structure of the input; it's your responsibility to ensure that the transformation produces a valid output. For example, if you're modifying a data frame, <code>.f</code> must preserve the length of the input. </p> <h3>Value</h3> <p>An object the same class as <code>.x</code> </p> <h3>Genericity</h3> <p><code>modify()</code> and variants are generic over classes that implement <code>length()</code>, <code>[[</code> and <code style="white-space: pre;">[[<-</code> methods. If the default implementation is not compatible for your class, you can override them with your own methods. </p> <p>If you implement your own <code>modify()</code> method, make sure it satisfies the following invariants:</p> <pre>modify(x, identity) === x modify(x, compose(f, g)) === modify(x, g) %>% modify(f) </pre> <p>These invariants are known as the <a href="https://wiki.haskell.org/Functor#Functor_Laws">functor laws</a> in computer science. </p> <h3>See Also</h3> <p>Other map variants: <code><a href="imap.html">imap</a>()</code>, <code><a href="invoke.html">invoke</a>()</code>, <code><a href="lmap.html">lmap</a>()</code>, <code><a href="map2.html">map2</a>()</code>, <code><a href="map_if.html">map_if</a>()</code>, <code><a href="map.html">map</a>()</code> </p> <h3>Examples</h3> <pre> # Convert factors to characters iris %>% modify_if(is.factor, as.character) %>% str() # Specify which columns to map with a numeric vector of positions: mtcars %>% modify_at(c(1, 4, 5), as.character) %>% str() # Or with a vector of names: mtcars %>% modify_at(c("cyl", "am"), as.character) %>% str() list(x = rbernoulli(100), y = 1:100) %>% transpose() %>% modify_if("x", ~ update_list(., y = ~ y * 100)) %>% transpose() %>% simplify_all() # Use modify2() to map over two vectors and preserve the type of # the first one: x <- c(foo = 1L, bar = 2L) y <- c(TRUE, FALSE) modify2(x, y, ~ if (.y) .x else 0L) # Use a predicate function to decide whether to map a function: modify_if(iris, is.factor, as.character) # Specify an alternative with the `.else` argument: modify_if(iris, is.factor, as.character, .else = as.integer) # Modify at specified depth --------------------------- l1 <- list( obj1 = list( prop1 = list(param1 = 1:2, param2 = 3:4), prop2 = list(param1 = 5:6, param2 = 7:8) ), obj2 = list( prop1 = list(param1 = 9:10, param2 = 11:12), prop2 = list(param1 = 12:14, param2 = 15:17) ) ) # In the above list, "obj" is level 1, "prop" is level 2 and "param" # is level 3. To apply sum() on all params, we map it at depth 3: l1 %>% modify_depth(3, sum) %>% str() # Note that vectorised operations will yield the same result when # applied at the list level as when applied at the atomic result. # The former is more efficient because it takes advantage of # vectorisation. l1 %>% modify_depth(3, `+`, 100L) l1 %>% modify_depth(4, `+`, 100L) # modify() lets us pluck the elements prop1/param2 in obj1 and obj2: l1 %>% modify(c("prop1", "param2")) %>% str() # But what if we want to pluck all param2 elements? Then we need to # act at a lower level: l1 %>% modify_depth(2, "param2") %>% str() # modify_depth() can be with other purrr functions to make them operate at # a lower level. Here we ask pmap() to map paste() simultaneously over all # elements of the objects at the second level. paste() is effectively # mapped at level 3. l1 %>% modify_depth(2, ~ pmap(., paste, sep = " / ")) %>% str() </pre> <hr /><div style="text-align: center;">[Package <em>purrr</em> version 0.3.4 <a href="00Index.html">Index</a>]</div> </body></html>