Search code examples
rpurrr

How do I map a function to each row in a tibble in R?


I am trying to map a function to each row in a tibble. Please see code below. My desired workflow is as follows -

  1. Convert a list with sub lists to a tibble
  2. Map each row the tibble to a function

My desired output should be a list with a tibble as output for each row mapped to the function. See full code below -

# Packages 
library(tidyverse)
library(purrr)

# Function i want to map
sample_func <- function(tib){
    
    a <- tib$name
    b <- tib$qty
    c <- tib$price
    d <- tib$add
    
    e <- b+c+d
    
    t <- tibble(e = c(e), stock = c(a))
    
    return(t)
    
}

# Define the list with multiple sublists
lst <- list(c( "CHR1", 15, 222.14, 6), c( "CHR2", 10, 119.20, 10))

# Convert each sublist to a tibble and bind the rows
tib <- bind_rows(lapply(lst, function(x) {
    tibble(name = x[1], qty = x[2] %>% as.numeric(), price = x[3] %>% as.numeric(), 
           add = x[4] %>% as.numeric())
}))

# Apply the function to each row in the tibble using map()
result <- tib %>% 
    rowwise() %>% 
    mutate(temp = map(list(name, qty, price, add), sample_func)) %>%
    unnest(temp)

My desired output should be -

[[1]]
# A tibble: 1 × 2
      e name 
  <dbl> <chr>
1  243. CHR1 

[[2]]
# A tibble: 1 × 2
      e name 
  <dbl> <chr>
1  139. CHR2 

However when the final rowwise mapping, I get the following error -

Error in `mutate()`:
! Problem while computing `temp = map(list(name, qty, price, add), sample_func)`.
ℹ The error occurred in row 1.
Caused by error in `map()`:
ℹ In index: 1.
Caused by error in `tib$name`:
! $ operator is invalid for atomic vectors

What am I doing wrong here?


Solution

  • An alternative approach is to change the inputs of the sample_func function to be the names of the columns instead of the tibble, then you can do this with pmap():

    # Function i want to map
    sample_func <- function(name, qty, price, add){
      
      a <- name
      b <- qty
      c <- price
      d <- add
      
      e <- b+c+d
      
      t <- tibble(e = c(e), stock = c(a))
      
      return(t)
      
    }
    
    # Define the list with multiple sublists
    lst <- list(c( "CHR1", 15, 222.14, 6), c( "CHR2", 10, 119.20, 10))
    
    # Convert each sublist to a tibble and bind the rows
    tib <- bind_rows(lapply(lst, function(x) {
      tibble(name = x[1], qty = x[2] %>% as.numeric(), price = x[3] %>% as.numeric(), 
             add = x[4] %>% as.numeric())
    }))
    
    # Apply the function to each row in the tibble using map()
    pmap(tib, sample_func)