Apply a function (or functions) across multiple columns — across (2024)

Apply a function (or functions) across multiple columns — across (1)

Source: R/across.R

across.Rd

across() makes it easy to apply the same transformation to multiplecolumns, allowing you to use select() semantics inside in "data-masking"functions like summarise() and mutate(). See vignette("colwise") formore details.

if_any() and if_all() apply the samepredicate function to a selection of columns and combine theresults into a single logical vector: if_any() is TRUE whenthe predicate is TRUE for any of the selected columns, if_all()is TRUE when the predicate is TRUE for all selected columns.

If you just need to select columns without applying a transformation to eachof them, then you probably want to use pick() instead.

across() supersedes the family of "scoped variants" likesummarise_at(), summarise_if(), and summarise_all().

Usage

across(.cols, .fns, ..., .names = NULL, .unpack = FALSE)if_any(.cols, .fns, ..., .names = NULL)if_all(.cols, .fns, ..., .names = NULL)

Arguments

.cols

<tidy-select> Columns to transform.You can't select grouping columns because they are already automaticallyhandled by the verb (i.e. summarise() or mutate()).

.fns

Functions to apply to each of the selected columns.Possible values are:

  • A function, e.g. mean.

  • A purrr-style lambda, e.g. ~ mean(.x, na.rm = TRUE)

  • A named list of functions or lambdas, e.g.list(mean = mean, n_miss = ~ sum(is.na(.x)). Each function is appliedto each column, and the output is named by combining the function nameand the column name using the glue specification in .names.

Within these functions you can use cur_column() and cur_group()to access the current column and grouping keys respectively.

...

Apply a function (or functions) across multiple columns — across (2)

Additional arguments for the function calls in .fns are no longeraccepted in ... because it's not clear when they should be evaluated:once per across() or once per group? Instead supply additional argumentsdirectly in .fns by using a lambda. For example, instead ofacross(a:b, mean, na.rm = TRUE) writeacross(a:b, ~ mean(.x, na.rm = TRUE)).

.names

A glue specification that describes how to name the outputcolumns. This can use {.col} to stand for the selected column name, and{.fn} to stand for the name of the function being applied. The default(NULL) is equivalent to "{.col}" for the single function case and"{.col}_{.fn}" for the case where a list is used for .fns.

.unpack

Apply a function (or functions) across multiple columns — across (3)

Optionally unpack data frames returned by functions in.fns, which expands the df-columns out into individual columns, retainingthe number of rows in the data frame.

  • If FALSE, the default, no unpacking is done.

  • If TRUE, unpacking is done with a default glue specification of"{outer}_{inner}".

  • Otherwise, a single glue specification can be supplied to describe how toname the unpacked columns. This can use {outer} to refer to the nameoriginally generated by .names, and {inner} to refer to the names ofthe data frame you are unpacking.

Value

across() typically returns a tibble with one column for each column in.cols and each function in .fns. If .unpack is used, more columns maybe returned depending on how the results of .fns are unpacked.

if_any() and if_all() return a logical vector.

Timing of evaluation

R code in dplyr verbs is generally evaluated once per group.Inside across() however, code is evaluated once for eachcombination of columns and groups. If the evaluation timing isimportant, for example if you're generating random variables, thinkabout when it should happen and place your code in consequence.

gdf <- tibble(g = c(1, 1, 2, 3), v1 = 10:13, v2 = 20:23) %>% group_by(g)set.seed(1)# Outside: 1 normal variaten <- rnorm(1)gdf %>% mutate(across(v1:v2, ~ .x + n))#> # A tibble: 4 x 3#> # Groups: g [3]#> g v1 v2#> <dbl> <dbl> <dbl>#> 1 1 9.37 19.4#> 2 1 10.4 20.4#> 3 2 11.4 21.4#> 4 3 12.4 22.4# Inside a verb: 3 normal variates (ngroup)gdf %>% mutate(n = rnorm(1), across(v1:v2, ~ .x + n))#> # A tibble: 4 x 4#> # Groups: g [3]#> g v1 v2 n#> <dbl> <dbl> <dbl> <dbl>#> 1 1 10.2 20.2 0.184#> 2 1 11.2 21.2 0.184#> 3 2 11.2 21.2 -0.836#> 4 3 14.6 24.6 1.60# Inside `across()`: 6 normal variates (ncol * ngroup)gdf %>% mutate(across(v1:v2, ~ .x + rnorm(1)))#> # A tibble: 4 x 3#> # Groups: g [3]#> g v1 v2#> <dbl> <dbl> <dbl>#> 1 1 10.3 20.7#> 2 1 11.3 21.7#> 3 2 11.2 22.6#> 4 3 13.5 22.7

See also

c_across() for a function that returns a vector

Examples

# For better printingiris <- as_tibble(iris)# across() -----------------------------------------------------------------# Different ways to select the same set of columns# See <https://tidyselect.r-lib.org/articles/syntax.html> for detailsiris %>% mutate(across(c(Sepal.Length, Sepal.Width), round))#> # A tibble: 150 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 5 4 1.4 0.2 setosa #>  2 5 3 1.4 0.2 setosa #>  3 5 3 1.3 0.2 setosa #>  4 5 3 1.5 0.2 setosa #>  5 5 4 1.4 0.2 setosa #>  6 5 4 1.7 0.4 setosa #>  7 5 3 1.4 0.3 setosa #>  8 5 3 1.5 0.2 setosa #>  9 4 3 1.4 0.2 setosa #> 10 5 3 1.5 0.1 setosa #> # ℹ 140 more rowsiris %>% mutate(across(c(1, 2), round))#> # A tibble: 150 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 5 4 1.4 0.2 setosa #>  2 5 3 1.4 0.2 setosa #>  3 5 3 1.3 0.2 setosa #>  4 5 3 1.5 0.2 setosa #>  5 5 4 1.4 0.2 setosa #>  6 5 4 1.7 0.4 setosa #>  7 5 3 1.4 0.3 setosa #>  8 5 3 1.5 0.2 setosa #>  9 4 3 1.4 0.2 setosa #> 10 5 3 1.5 0.1 setosa #> # ℹ 140 more rowsiris %>% mutate(across(1:Sepal.Width, round))#> # A tibble: 150 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 5 4 1.4 0.2 setosa #>  2 5 3 1.4 0.2 setosa #>  3 5 3 1.3 0.2 setosa #>  4 5 3 1.5 0.2 setosa #>  5 5 4 1.4 0.2 setosa #>  6 5 4 1.7 0.4 setosa #>  7 5 3 1.4 0.3 setosa #>  8 5 3 1.5 0.2 setosa #>  9 4 3 1.4 0.2 setosa #> 10 5 3 1.5 0.1 setosa #> # ℹ 140 more rowsiris %>% mutate(across(where(is.double) & !c(Petal.Length, Petal.Width), round))#> # A tibble: 150 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 5 4 1.4 0.2 setosa #>  2 5 3 1.4 0.2 setosa #>  3 5 3 1.3 0.2 setosa #>  4 5 3 1.5 0.2 setosa #>  5 5 4 1.4 0.2 setosa #>  6 5 4 1.7 0.4 setosa #>  7 5 3 1.4 0.3 setosa #>  8 5 3 1.5 0.2 setosa #>  9 4 3 1.4 0.2 setosa #> 10 5 3 1.5 0.1 setosa #> # ℹ 140 more rows# Using an external vector of namescols <- c("Sepal.Length", "Petal.Width")iris %>% mutate(across(all_of(cols), round))#> # A tibble: 150 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 5 3.5 1.4 0 setosa #>  2 5 3 1.4 0 setosa #>  3 5 3.2 1.3 0 setosa #>  4 5 3.1 1.5 0 setosa #>  5 5 3.6 1.4 0 setosa #>  6 5 3.9 1.7 0 setosa #>  7 5 3.4 1.4 0 setosa #>  8 5 3.4 1.5 0 setosa #>  9 4 2.9 1.4 0 setosa #> 10 5 3.1 1.5 0 setosa #> # ℹ 140 more rows# If the external vector is named, the output columns will be named according# to those namesnames(cols) <- tolower(cols)iris %>% mutate(across(all_of(cols), round))#> # A tibble: 150 × 7#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species sepal.length#> <dbl> <dbl> <dbl> <dbl> <fct> <dbl>#>  1 5.1 3.5 1.4 0.2 setosa 5#>  2 4.9 3 1.4 0.2 setosa 5#>  3 4.7 3.2 1.3 0.2 setosa 5#>  4 4.6 3.1 1.5 0.2 setosa 5#>  5 5 3.6 1.4 0.2 setosa 5#>  6 5.4 3.9 1.7 0.4 setosa 5#>  7 4.6 3.4 1.4 0.3 setosa 5#>  8 5 3.4 1.5 0.2 setosa 5#>  9 4.4 2.9 1.4 0.2 setosa 4#> 10 4.9 3.1 1.5 0.1 setosa 5#> # ℹ 140 more rows#> # ℹ 1 more variable: petal.width <dbl># A purrr-style formulairis %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), ~ mean(.x, na.rm = TRUE)))#> # A tibble: 3 × 3#> Species Sepal.Length Sepal.Width#> <fct> <dbl> <dbl>#> 1 setosa 5.01 3.43#> 2 versicolor 5.94 2.77#> 3 virginica 6.59 2.97# A named list of functionsiris %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), list(mean = mean, sd = sd)))#> # A tibble: 3 × 5#> Species Sepal.Length_mean Sepal.Length_sd Sepal.Width_mean#> <fct> <dbl> <dbl> <dbl>#> 1 setosa 5.01 0.352 3.43#> 2 versicolor 5.94 0.516 2.77#> 3 virginica 6.59 0.636 2.97#> # ℹ 1 more variable: Sepal.Width_sd <dbl># Use the .names argument to control the output namesiris %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), mean, .names = "mean_{.col}"))#> # A tibble: 3 × 3#> Species mean_Sepal.Length mean_Sepal.Width#> <fct> <dbl> <dbl>#> 1 setosa 5.01 3.43#> 2 versicolor 5.94 2.77#> 3 virginica 6.59 2.97iris %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), list(mean = mean, sd = sd), .names = "{.col}.{.fn}"))#> # A tibble: 3 × 5#> Species Sepal.Length.mean Sepal.Length.sd Sepal.Width.mean#> <fct> <dbl> <dbl> <dbl>#> 1 setosa 5.01 0.352 3.43#> 2 versicolor 5.94 0.516 2.77#> 3 virginica 6.59 0.636 2.97#> # ℹ 1 more variable: Sepal.Width.sd <dbl># If a named external vector is used for column selection, .names will use# those names when constructing the output namesiris %>% group_by(Species) %>% summarise(across(all_of(cols), mean, .names = "mean_{.col}"))#> # A tibble: 3 × 3#> Species mean_sepal.length mean_petal.width#> <fct> <dbl> <dbl>#> 1 setosa 5.01 0.246#> 2 versicolor 5.94 1.33 #> 3 virginica 6.59 2.03 # When the list is not named, .fn is replaced by the function's positioniris %>% group_by(Species) %>% summarise(across(starts_with("Sepal"), list(mean, sd), .names = "{.col}.fn{.fn}"))#> # A tibble: 3 × 5#> Species Sepal.Length.fn1 Sepal.Length.fn2 Sepal.Width.fn1#> <fct> <dbl> <dbl> <dbl>#> 1 setosa 5.01 0.352 3.43#> 2 versicolor 5.94 0.516 2.77#> 3 virginica 6.59 0.636 2.97#> # ℹ 1 more variable: Sepal.Width.fn2 <dbl># When the functions in .fns return a data frame, you typically get a# "packed" data frame backquantile_df <- function(x, probs = c(0.25, 0.5, 0.75)) { tibble(quantile = probs, value = quantile(x, probs))}iris %>% reframe(across(starts_with("Sepal"), quantile_df))#> # A tibble: 3 × 2#> Sepal.Length$quantile $value Sepal.Width$quantile $value#> <dbl> <dbl> <dbl> <dbl>#> 1 0.25 5.1 0.25 2.8#> 2 0.5 5.8 0.5 3 #> 3 0.75 6.4 0.75 3.3# Use .unpack to automatically expand these packed data frames into their# individual columnsiris %>% reframe(across(starts_with("Sepal"), quantile_df, .unpack = TRUE))#> # A tibble: 3 × 4#> Sepal.Length_quantile Sepal.Length_value Sepal.Width_quantile#> <dbl> <dbl> <dbl>#> 1 0.25 5.1 0.25#> 2 0.5 5.8 0.5 #> 3 0.75 6.4 0.75#> # ℹ 1 more variable: Sepal.Width_value <dbl># .unpack can utilize a glue specification if you don't like the defaultsiris %>% reframe(across(starts_with("Sepal"), quantile_df, .unpack = "{outer}.{inner}"))#> # A tibble: 3 × 4#> Sepal.Length.quantile Sepal.Length.value Sepal.Width.quantile#> <dbl> <dbl> <dbl>#> 1 0.25 5.1 0.25#> 2 0.5 5.8 0.5 #> 3 0.75 6.4 0.75#> # ℹ 1 more variable: Sepal.Width.value <dbl># This is also useful inside mutate(), for example, with a multi-lag helpermultilag <- function(x, lags = 1:3) { names(lags) <- as.character(lags) purrr::map_dfr(lags, lag, x = x)}iris %>% group_by(Species) %>% mutate(across(starts_with("Sepal"), multilag, .unpack = TRUE)) %>% select(Species, starts_with("Sepal"))#> # A tibble: 150 × 9#> # Groups: Species [3]#> Species Sepal.Length Sepal.Width Sepal.Length_1 Sepal.Length_2#> <fct> <dbl> <dbl> <dbl> <dbl>#>  1 setosa 5.1 3.5 NA NA #>  2 setosa 4.9 3 5.1 NA #>  3 setosa 4.7 3.2 4.9 5.1#>  4 setosa 4.6 3.1 4.7 4.9#>  5 setosa 5 3.6 4.6 4.7#>  6 setosa 5.4 3.9 5 4.6#>  7 setosa 4.6 3.4 5.4 5 #>  8 setosa 5 3.4 4.6 5.4#>  9 setosa 4.4 2.9 5 4.6#> 10 setosa 4.9 3.1 4.4 5 #> # ℹ 140 more rows#> # ℹ 4 more variables: Sepal.Length_3 <dbl>, Sepal.Width_1 <dbl>,#> # Sepal.Width_2 <dbl>, Sepal.Width_3 <dbl># if_any() and if_all() ----------------------------------------------------iris %>% filter(if_any(ends_with("Width"), ~ . > 4))#> # A tibble: 3 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species#> <dbl> <dbl> <dbl> <dbl> <fct> #> 1 5.7 4.4 1.5 0.4 setosa #> 2 5.2 4.1 1.5 0.1 setosa #> 3 5.5 4.2 1.4 0.2 setosa iris %>% filter(if_all(ends_with("Width"), ~ . > 2))#> # A tibble: 23 × 5#> Sepal.Length Sepal.Width Petal.Length Petal.Width Species #> <dbl> <dbl> <dbl> <dbl> <fct> #>  1 6.3 3.3 6 2.5 virginica#>  2 7.1 3 5.9 2.1 virginica#>  3 6.5 3 5.8 2.2 virginica#>  4 7.6 3 6.6 2.1 virginica#>  5 7.2 3.6 6.1 2.5 virginica#>  6 6.8 3 5.5 2.1 virginica#>  7 5.8 2.8 5.1 2.4 virginica#>  8 6.4 3.2 5.3 2.3 virginica#>  9 7.7 3.8 6.7 2.2 virginica#> 10 7.7 2.6 6.9 2.3 virginica#> # ℹ 13 more rows
Apply a function (or functions) across multiple columns — across (2024)

References

Top Articles
Maharashtra State Board of Technical Education, Mumbai , India
Pros and Cons of Living in Mountain Home, Idaho - Citytistics
Funny Roblox Id Codes 2023
Golden Abyss - Chapter 5 - Lunar_Angel
Www.paystubportal.com/7-11 Login
Joi Databas
DPhil Research - List of thesis titles
Shs Games 1V1 Lol
Evil Dead Rise Showtimes Near Massena Movieplex
Steamy Afternoon With Handsome Fernando
Which aspects are important in sales |#1 Prospection
Detroit Lions 50 50
18443168434
Newgate Honda
Zürich Stadion Letzigrund detailed interactive seating plan with seat & row numbers | Sitzplan Saalplan with Sitzplatz & Reihen Nummerierung
Grace Caroline Deepfake
978-0137606801
Nwi Arrests Lake County
Justified Official Series Trailer
London Ups Store
Committees Of Correspondence | Encyclopedia.com
Pizza Hut In Dinuba
Jinx Chapter 24: Release Date, Spoilers & Where To Read - OtakuKart
How Much You Should Be Tipping For Beauty Services - American Beauty Institute
Free Online Games on CrazyGames | Play Now!
Sizewise Stat Login
VERHUURD: Barentszstraat 12 in 'S-Gravenhage 2518 XG: Woonhuis.
Jet Ski Rental Conneaut Lake Pa
Unforeseen Drama: The Tower of Terror’s Mysterious Closure at Walt Disney World
Ups Print Store Near Me
C&T Wok Menu - Morrisville, NC Restaurant
How Taraswrld Leaks Exposed the Dark Side of TikTok Fame
University Of Michigan Paging System
Dashboard Unt
Access a Shared Resource | Computing for Arts + Sciences
Speechwire Login
Healthy Kaiserpermanente Org Sign On
Restored Republic
3473372961
Craigslist Gigs Norfolk
Moxfield Deck Builder
Senior Houses For Sale Near Me
Whitehall Preparatory And Fitness Academy Calendar
Trivago Myrtle Beach Hotels
Anya Banerjee Feet
Three V Plymouth
Thotsbook Com
Funkin' on the Heights
Vci Classified Paducah
Www Pig11 Net
Ty Glass Sentenced
Latest Posts
Article information

Author: Cheryll Lueilwitz

Last Updated:

Views: 6013

Rating: 4.3 / 5 (74 voted)

Reviews: 89% of readers found this page helpful

Author information

Name: Cheryll Lueilwitz

Birthday: 1997-12-23

Address: 4653 O'Kon Hill, Lake Juanstad, AR 65469

Phone: +494124489301

Job: Marketing Representative

Hobby: Reading, Ice skating, Foraging, BASE jumping, Hiking, Skateboarding, Kayaking

Introduction: My name is Cheryll Lueilwitz, I am a sparkling, clean, super, lucky, joyous, outstanding, lucky person who loves writing and wants to share my knowledge and understanding with you.