Gert
Gert

Reputation: 21

How to use dplyr's rowwise() in pipe in R to apply a function that returns a list to each row?

I would like to use dplyr's rowwise() and the pipe to apply a function (that returns a list) to each row in the dataframe.

Test dataset with two rows:

test_tbl <- tibble(a=c(2, 4), b=c(0, 8), c=c(5, -3))

Defining a simple function (it's about a function returning a list, obviously not about adding 8):

simple_function <- function(input) {
  list(input + 8)
}

This is what I would like to achieve:

apply(test_tbl ,1, function (x) simple_function(x))

which returns a list of 2 lists (my desired output).

I would like to save those lists as a column in the tibble. We could do:

test_tbl %>% mutate(output = apply(. ,1, function (x) simple_function(x)))

I'd rather use dplyr than mixing up dplyr, base, and the pipe (also for readability of code), but I do not understand why this doesn't work:

test_tbl %>% rowwise() %>% simple_function
test_tbl %>% rowwise() %>% mutate(output = simple_function(.))

Both of these functions apply the function to the entire dataframe rather than to the seperate rows. It makes no sense to me that: test_tbl %>% rowwise() %>% simple_function is identical (in terms of output) to test_tbl %>% simple_function

This does give the desired output, but I find it rather verbose and not ideal that I have to bind the columns myself:

test_tbl %>% rowwise() %>% do(output= simple_function(.)) %>% bind_cols(test_tbl, .)

Any help on why rowwise() is failing is much appreciated.

Upvotes: 2

Views: 1869

Answers (1)

akrun
akrun

Reputation: 887223

If we need to do this on each row, then split and apply the function within map

library(tidyverse)
test_tbl %>% 
    split(., seq_len(nrow(.))) %>%
    map(simple_function)
#$`1`
#$`1`[[1]]
#   a b  c
#1 10 8 13


#$`2`
#$`2`[[1]]
#   a  b c
#1 12 16 5

Upvotes: 2

Related Questions