vec_map: Apply a function to each element of a vector

Description Usage Arguments Details Invariants Examples

Description

vec_map() is like purrr::map(), but can automatically simplify the output based on vctrs type rules. This does away with the need for variants such as map_dbl(), and is more expressive because the output type can be anything, for example, a Date vector.

Usage

1
vec_map(.x, .f, ..., .ptype = NULL)

Arguments

.x

A list or atomic vector.

.f

A function, formula, or vector (not necessarily atomic).

If a function, it is used as is.

If a formula, e.g. ~ .x + 2, it is converted to a function. There are three ways to refer to the arguments:

  • For a single argument function, use .

  • For a two argument function, use .x and .y

  • For more arguments, use ..1, ..2, ..3 etc

This syntax allows you to create very compact anonymous functions.

If character vector, numeric vector, or list, 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 .default will be returned.

...

Additional arguments passed on to the mapped function.

.ptype

A prototype for the output container. If NULL, a common type is determined from the individual results of the map(). If no common type can be determined, the output container is a list().

Details

If .ptype = NULL, the common type of the results of the map() will attempt to be determined. If a common type can be found, then the result will be simplified to that type. Otherwise, a list is returned.

If a common type is found, it is a requirement that every element have size 1. This enforces the invariant that the size of the input is the same size as the output.

You can force an output type by specifying the .ptype. For example, specifying .ptype = double() is equivalent to map_dbl().

Setting .ptype = list() is equivalent to map().

Invariants

vec_size(.x) == vec_size(vec_map(.x))

Examples

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
library(vctrs)

# Auto simplified to an integer vector
vec_map(1:2, ~ .x)

# Prevent simplification with `.ptype = list()`
vec_map(1:2, ~ .x, .ptype = list())

# If a `.ptype` is specified, and casting to that type
# is not possible, an error is raised
try(vec_map(1:2, ~ .x, .ptype = factor()))

# If simplification is possible, all elements must have size 1,
# otherwise an error is raised
try(vec_map(1:2, ~ if (.x == 1L) 1:2 else 3))

# But if you use `.ptype = list()`, this is relaxed
# (However, note that the size of the output is still the
# same as the size of the input (2), this is the key!)
vec_map(1:2, ~ if (.x == 1L) 1:2 else 3, .ptype = list())

# The best thing about `vec_map()` is its flexibility with other
# non-atomic types, for example, simplifying to a date vector
vec_map(1:2, ~ Sys.Date() + .x)

# If a common type cannot be determined, a list is returned
vec_map(list(1, "x"), ~ .x)

# Note that just because a common type isn't found, doesn't mean you
# can't still coerce to a certain type. This is the difference between
# _coercion_ (automatic type casting) and a _cast_ which is slightly more
# flexible because you are specifically requesting the output type.
vec_map(list(1, "x"), ~ .x, .ptype = character())

# Data frames work too
vec_map(1:2, ~ data.frame(x = .x))

# You can enforce the structure of the data frame output with a ptype.
# This has the same result as before but coerces the integers to characters
ptype <- data.frame(x = character(), stringsAsFactors = FALSE)
vec_map(1:2, ~ data.frame(x = .x), .ptype = ptype)

# Or you can enforce a partial structure with a partial_frame()
partial_ptype <- partial_frame(y = numeric())
vec_map(1:2, ~ data.frame(x = .x, y = .x + 1), .ptype = partial_ptype)

DavisVaughan/vcturrrs documentation built on June 17, 2019, 12:01 a.m.