Skip to contents

Applies an expression to each row and assignes it to a new column. Per-row failures are handled with default values (NAs) or can be intercepted by the user with a tryCatch(...) expression. There are many other ways to do a similar thing in `dplyr` and `purrr` but they are all more complicated than I expect them to be.

Usage

rowwise_mutate(.data, ..., .onerror = function(e, ...) NA)

Arguments

.data

a dataframe. grouping is ingnored

...

a named list of expressions similar to mutate but where the expressions to be evaluated are evaluated in only in the context of the current row - and are not vectorised. This does not support [dplyr::accross] syntax.

.onerror

a function that is called for

Value

a dataframe the same length as input with additional or altered columns

Examples

# calculations are scoped only to current row. Hence max(x) == x always:
iris %>% rowwise_mutate(
  widths = Sepal.Width+max(Petal.Width),
  lengths = Sepal.Length+max(Petal.Length),
  tmp = tibble::tibble(a=1, b=2)) %>%
dplyr::glimpse()
#> Rows: 150
#> Columns: 8
#> $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
#> $ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
#> $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
#> $ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
#> $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…
#> $ widths       <dbl> 3.7, 3.2, 3.4, 3.3, 3.8, 4.3, 3.7, 3.6, 3.1, 3.2, 3.9, 3.…
#> $ lengths      <dbl> 6.5, 6.3, 6.0, 6.1, 6.4, 7.1, 6.0, 6.5, 5.8, 6.4, 6.9, 6.…
#> $ tmp          <list> [<tbl_df[1 x 2]>], [<tbl_df[1 x 2]>], [<tbl_df[1 x 2]>],…

# This is different to standard dplyr behaviour when the additional tibble
# column is considered. standard dplyr rowwise does something unexpected:
iris %>% dplyr::rowwise() %>% dplyr::mutate(
  widths = Sepal.Width+max(Petal.Width),
  lengths = Sepal.Length+max(Petal.Length),
  tmp = tibble::tibble(a=1, b=2)) %>%
dplyr::glimpse()
#> Rows: 150
#> Columns: 8
#> Rowwise: 
#> $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
#> $ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
#> $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
#> $ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
#> $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…
#> $ widths       <dbl> 3.7, 3.2, 3.4, 3.3, 3.8, 4.3, 3.7, 3.6, 3.1, 3.2, 3.9, 3.…
#> $ lengths      <dbl> 6.5, 6.3, 6.0, 6.1, 6.4, 7.1, 6.0, 6.5, 5.8, 6.4, 6.9, 6.…
#> $ tmp          <tibble[,2]> <tbl_df[26 x 2]>

# As expressions are not vectorised we can use normal if ... else ... statements
# and errors can be handled and default values provided.
suppressWarnings(
iris %>% rowwise_mutate(
  tmp = if (Petal.Width > 2.0) stop("error message: ",Petal.Width) else Petal.Width,
  .onerror = function(e) -Petal.Width
) %>%
dplyr::glimpse()
)
#> Rows: 150
#> Columns: 6
#> $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
#> $ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
#> $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
#> $ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
#> $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…
#> $ tmp          <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…

# The default values
# are evaluated in the same context as the original expression, but only are
# defaults for all the columns so makes most sense when a default value is given

suppressWarnings(
iris %>% rowwise_mutate(
  tmp = if (Petal.Width > 2.0) stop("too wide petals: ",Petal.Width) else Petal.Width,
  tmp2 = if (Sepal.Width > 4) stop("too wide sepals: ",Sepal.Width) else Sepal.Width,
  .onerror = function(e) Inf
) %>%
dplyr::glimpse()
)
#> Rows: 150
#> Columns: 7
#> $ Sepal.Length <dbl> 5.1, 4.9, 4.7, 4.6, 5.0, 5.4, 4.6, 5.0, 4.4, 4.9, 5.4, 4.…
#> $ Sepal.Width  <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…
#> $ Petal.Length <dbl> 1.4, 1.4, 1.3, 1.5, 1.4, 1.7, 1.4, 1.5, 1.4, 1.5, 1.5, 1.…
#> $ Petal.Width  <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
#> $ Species      <fct> setosa, setosa, setosa, setosa, setosa, setosa, setosa, s…
#> $ tmp          <dbl> 0.2, 0.2, 0.2, 0.2, 0.2, 0.4, 0.3, 0.2, 0.2, 0.1, 0.2, 0.…
#> $ tmp2         <dbl> 3.5, 3.0, 3.2, 3.1, 3.6, 3.9, 3.4, 3.4, 2.9, 3.1, 3.7, 3.…