Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of next in purrr::map_df

Tags:

r

purrr

tidyverse

I am looking for the equivalent of next in loops for a purrr::map_df call.

map_df plays nicely with dataframes that are NULL (as in the example below), so it works when I set Result <- NULL in my example below.

Could anyone suggest a general solution to my illustration below that would not require me setting Result <- NULL, but rather immediately go "next".

library(tidyverse)
set.seed(1000)

df <- data.frame(x = rnorm(100), y = rnorm(100), z = rep(LETTERS, 100))

Map_Func <- function(df) {

  Sum_Num <- suppressWarnings(sqrt(sum(df$y)))

  if( Sum_Num == "NaN" ) {

    Result <- NULL
    # I would like to have an equivalent to "next" here... 

    } else {

  Result <- df %>% filter(y == max(y)) %>% mutate(Result = x*y)

}

Result

}

Test <- split(df, df$z) %>% map_df(~Map_Func(.))

In the code above, what can I use instead of Result <- NULL in the ugly if statement (i.e. I want to simply check a condition and effectively do a "next").

like image 552
Nick Avatar asked Oct 16 '25 16:10

Nick


2 Answers

To exit a function you can use the return(<output>) command. This immediately exits the function with the output you define. The following gives the same output you were getting with your sample code.

library(tidyverse)
set.seed(1000)

df <- data.frame(x = rnorm(100), y = rnorm(100), z = rep(LETTERS, 100))

Map_Func <- function(df) {

  Sum_Num <- suppressWarnings(sqrt(sum(df$y)))

  if( Sum_Num == "NaN" ) {

    return(NULL)

  } 

  Result <- df %>% filter(y == max(y)) %>% mutate(Result = x*y)
}

Test <- split(df, df$z) %>% map_df(~Map_Func(.))
like image 190
Adam Sampson Avatar answered Oct 19 '25 07:10

Adam Sampson


Logic wise not a very different solution than OP but trying to keep it clean by using separate functions. custom_check function is to check the condition for each group. Using map_if we apply the function Map_Func_true only when custom_check returns TRUE or else apply Map_Func_false which returns NULL and finally bind the rows.

library(tidyverse)

Map_Func_true <- function(df) {
  df %>% filter(y == max(y)) %>% mutate(Result = x*y)
}

Map_Func_false <- function(df) { return(NULL) }

custom_check <- function(df) {
    !is.nan(suppressWarnings(sqrt(sum(df$y))))
}


df %>%
  group_split(z) %>%
  map_if(., custom_check, Map_Func_true, .else = Map_Func_false) %>%
  bind_rows()


# A tibble: 26 x 4
#       x     y z     Result
#   <dbl> <dbl> <fct>  <dbl>
# 1  1.24  2.00 A       2.47
# 2  1.24  2.00 A       2.47
# 3  1.24  2.00 C       2.47
# 4  1.24  2.00 C       2.47
# 5  1.24  2.00 E       2.47
# 6  1.24  2.00 E       2.47
# 7  1.24  2.00 G       2.47
# 8  1.24  2.00 G       2.47
# 9  1.24  2.00 I       2.47
#10  1.24  2.00 I       2.47
# … with 16 more rows
like image 32
Ronak Shah Avatar answered Oct 19 '25 07:10

Ronak Shah