The map functions transform their input by applying a function to each element of a list or atomic vector and returning an object of the same length as the input.
map()always returns a list. See themodify()family for versions that return an object of the same type as the input.map_lgl(),map_int(),map_dbl()andmap_chr()return an atomic vector of the indicated type (or die trying).map_dfr()andmap_dfc()return a data frame created by row-binding and column-binding respectively. They require dplyr to be installed.The returned values of
.fmust be of length one for each element of.x. If.fuses an extractor function shortcut,.defaultcan be specified to handle values that are absent or empty. Seeas_mapper()for more on.default.
walk()calls.ffor its side-effect and returns the input.x.
Usage
map(.x, .f, ...)
map_lgl(.x, .f, ...)
map_chr(.x, .f, ...)
map_int(.x, .f, ...)
map_dbl(.x, .f, ...)
map_raw(.x, .f, ...)
map_dfr(.x, .f, ..., .id = NULL)
map_dfc(.x, .f, ...)
walk(.x, .f, ...)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
.xand.yFor more arguments, use
..1,..2,..3etc
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
.defaultwill be returned.- ...
Additional arguments passed on to the mapped function.
- .id
Either a string or
NULL. If a string, the output will contain a variable with that name, storing either the name (if.xis named) or the index (if.xis unnamed) of the input. IfNULL, the default, no variable will be created.Only applies to
_dfrvariant.
Value
map()Returns a list the same length as.x.map_lgl()returns a logical vector,map_int()an integer vector,map_dbl()a double vector, andmap_chr()a character vector.map_df(),map_dfc(),map_dfr()all return a data frame.If
.xhasnames(), the return value preserves those names.The output of
.fwill be automatically typed upwards, e.g. logical -> integer -> double -> character.
walk()returns the input.x(invisibly). This makes it easy to use in pipe.
Examples
# Compute normal distributions from an atomic vector
1:10 %>%
map(rnorm, n = 10)
#> [[1]]
#> [1] -0.33005266 1.16938020 0.51461548 0.50764934 0.77118524
#> [6] 0.59358665 2.05278168 -0.84082226 -0.03995567 1.23740174
#>
#> [[2]]
#> [1] 0.4023269 1.3600169 1.6765932 0.4165575 3.0479110 2.9257833 2.8297412
#> [8] 3.8556399 2.6632916 2.1175712
#>
#> [[3]]
#> [1] 2.920256 2.148360 3.190512 2.869541 3.932535 3.722460 3.688649
#> [8] 2.996824 2.447696 3.391930
#>
#> [[4]]
#> [1] 3.928121 4.124139 5.690892 6.342451 4.331546 6.202030 4.418203
#> [8] 4.626108 4.362771 4.645633
#>
#> [[5]]
#> [1] 5.510729 2.440301 4.987308 3.030024 3.565450 5.124508 4.282498
#> [8] 6.967879 3.656479 6.198227
#>
#> [[6]]
#> [1] 7.477078 6.960283 4.990668 6.675381 5.092740 6.191480 6.937200
#> [8] 4.670206 5.554705 6.060998
#>
#> [[7]]
#> [1] 5.689300 5.971133 4.787184 6.665550 6.901558 7.104542 5.073075
#> [8] 6.597985 6.549152 6.843425
#>
#> [[8]]
#> [1] 8.922526 7.873473 6.377009 7.740205 8.399335 8.134439 6.814899
#> [8] 8.459502 7.263681 7.355401
#>
#> [[9]]
#> [1] 10.045095 6.078727 10.334559 10.571744 8.522265 9.559503 8.404625
#> [8] 10.304109 8.540005 9.338297
#>
#> [[10]]
#> [1] 11.081518 10.300762 10.103314 11.101992 9.746213 9.223091 7.714598
#> [8] 11.717469 9.935019 11.055381
#>
# You can also use an anonymous function
1:10 %>%
map(function(x) rnorm(10, x))
#> [[1]]
#> [1] 1.51073576 1.44189335 0.59996713 -0.31657382 0.68946511
#> [6] 2.42577099 3.41264039 0.61613253 -0.63238493 0.03027404
#>
#> [[2]]
#> [1] 0.7715523 2.8458921 2.8601112 3.4155083 3.0038757 1.6716353 1.4697428
#> [8] 2.3065674 1.6010469 1.5371903
#>
#> [[3]]
#> [1] 3.601926 1.320165 2.031204 2.684637 2.636041 2.589475 2.882947
#> [8] 3.685277 2.861452 2.718697
#>
#> [[4]]
#> [1] 4.841020 2.246810 2.919041 4.167942 3.263133 3.918789 4.508736
#> [8] 3.216942 4.128173 6.428031
#>
#> [[5]]
#> [1] 5.799355 5.223523 4.232092 5.085557 5.550274 6.023162 7.024083
#> [8] 5.514186 4.080235 4.071218
#>
#> [[6]]
#> [1] 6.288740 6.143478 6.439365 6.044262 6.999850 6.122501 5.424881
#> [8] 5.919893 5.956319 7.137929
#>
#> [[7]]
#> [1] 5.505915 5.212710 7.341394 9.733964 8.154294 5.005580 7.437616
#> [8] 7.270275 5.339835 7.113426
#>
#> [[8]]
#> [1] 8.736630 8.097831 8.386212 8.352851 9.279395 8.937042 7.847974
#> [8] 7.457611 6.871598 8.225599
#>
#> [[9]]
#> [1] 7.889781 6.722619 8.180109 9.045687 9.075177 7.990847 8.913990
#> [8] 8.608053 8.059512 9.938671
#>
#> [[10]]
#> [1] 8.559418 9.431864 10.233176 10.138606 10.916264 10.831297 9.122666
#> [8] 9.920924 9.611978 10.887876
#>
# Or a formula
1:10 %>%
map(~ rnorm(10, .x))
#> [[1]]
#> [1] 1.3705025 -0.8475769 -1.0836770 1.4754134 1.0154841 0.7195109
#> [7] -1.9092978 1.6748726 0.5151697 -0.3697344
#>
#> [[2]]
#> [1] 2.542304 3.053414 3.322603 1.912702 2.647517 1.342681 2.145057
#> [8] 3.149783 2.661671 2.428057
#>
#> [[3]]
#> [1] 1.860268 3.969342 3.400718 3.616287 3.424801 4.595332 2.924648
#> [8] 2.771398 3.085583 1.950685
#>
#> [[4]]
#> [1] 2.968975 3.549948 4.893061 4.176134 3.371122 3.862740 4.238757
#> [8] 3.328407 3.441108 4.942307
#>
#> [[5]]
#> [1] 5.243776 4.972958 3.792386 4.683212 5.422046 4.267013 4.504570
#> [8] 5.783662 4.608725 4.170206
#>
#> [[6]]
#> [1] 5.500425 8.071588 6.502481 4.053161 6.704480 5.630803 7.967160
#> [8] 5.274310 5.872336 7.245665
#>
#> [[7]]
#> [1] 8.153672 7.545571 5.659837 7.646695 7.025130 6.913479 7.132289
#> [8] 6.537969 7.131020 7.472515
#>
#> [[8]]
#> [1] 7.236522 6.970660 7.217738 7.917837 8.218194 7.067140 5.599998
#> [8] 7.569683 7.532446 6.345580
#>
#> [[9]]
#> [1] 9.631674 8.724814 9.149855 9.178104 8.327091 9.919226 8.543936
#> [8] 10.565467 8.705109 9.212858
#>
#> [[10]]
#> [1] 10.828820 10.622347 10.276298 11.267222 11.296271 10.312032 9.472046
#> [8] 8.413754 10.447023 10.225880
#>
# Simplify output to a vector instead of a list by computing the mean of the distributions
1:10 %>%
map(rnorm, n = 10) %>% # output a list
map_dbl(mean) # output an atomic vector
#> [1] 1.169039 2.476506 2.779545 4.039582 5.367765 6.500865 7.203717
#> [8] 8.242913 8.844403 10.140176
# Using set_names() with character vectors is handy to keep track
# of the original inputs:
set_names(c("foo", "bar")) %>% map_chr(paste0, ":suffix")
#> foo bar
#> "foo:suffix" "bar:suffix"
# Working with lists
favorite_desserts <- list(Sophia = "banana bread", Eliott = "pancakes", Karina = "chocolate cake")
favorite_desserts %>% map_chr(~ paste(.x, "rocks!"))
#> Sophia Eliott Karina
#> "banana bread rocks!" "pancakes rocks!" "chocolate cake rocks!"
# 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 = "???")
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] "???"
#>
#> [[3]]
#> [1] "???"
#>
l1 %>% map_int("b", .default = NA)
#> [1] NA 2 3
l1 %>% map_int(2, .default = NA)
#> [1] NA 2 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))
#> [[1]]
#> [1] "b"
#>
#> [[2]]
#> [1] "e"
#>
#> [[3]]
#> NULL
#>
# 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))
#> [[1]]
#> [1] 3
#>
#> [[2]]
#> [1] 103
#>
#> [[3]]
#> NULL
#>
l2 %>% map_int(list("num", 3), .default = NA)
#> [1] 3 103 NA
# Working with data frames
# Use map_lgl(), map_dbl(), etc to return a vector instead of a list:
mtcars %>% map_dbl(sum)
#> mpg cyl disp hp drat wt qsec vs
#> 642.900 198.000 7383.100 4694.000 115.090 102.952 571.160 14.000
#> am gear carb
#> 13.000 118.000 90.000
# 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")
#> 4 6 8
#> 0.5086326 0.4645102 0.4229655
# 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(.)))))
#> (Intercept) wt
#> 1 39.57120 -5.647025
#> 2 28.40884 -2.780106
#> 3 23.86803 -2.192438
# (if you also want to preserve the variable names see
# the broom package)
