简体   繁体   中英

Adding optional arguments to functions in R

why does this work?

createTibble <- function(i, yr, wk){
  if(missing(wk)){
    list_sheets[[i]]%>%
      filter(LASTUSER %in% users ) %>% 
      mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
             month = as.numeric(format(DATEMODIFI, format = "%m")),
             week = week(DATEMODIFI),
             day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
      select(-DATEMODIFI) %>% 
      filter(year == yr)
  } else{
    list_sheets[[i]]%>%
      filter(LASTUSER %in% users ) %>% 
      mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
             month = as.numeric(format(DATEMODIFI, format = "%m")),
             week = week(DATEMODIFI),
             day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
      select(-DATEMODIFI) %>% 
      filter(year == yr) %>%
      filter(week == wk)

    }
}

but not this?

createTibble <- function(i, yr, wk){
  list_sheets[[i]]%>%
    filter(LASTUSER %in% users ) %>% 
    mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
           month = as.numeric(format(DATEMODIFI, format = "%m")),
           week = week(DATEMODIFI),
           day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
    select(-DATEMODIFI) %>%
    if_else(missing(wk),filter(year == yr),filter(year == yr) %>% filter(week == wk)) }
Error: `condition` must be a logical vector, not a `tbl_df/tbl/data.frame` object
Run `rlang::last_error()` to see where the error occurred. 

The top works but I don't want to repeat the same code twice. Is there a way to use if_else() with this type of argument? or do I need to do something else?

Try using if in filter

library(dplyr)

createTibble <- function(i, yr, wk){
  is_missing <- missing(wk)
  list_sheets[[i]]%>%
    filter(LASTUSER %in% users ) %>% 
    mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
           month = as.numeric(format(DATEMODIFI, format = "%m")),
           week = week(DATEMODIFI),
           day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
    select(-DATEMODIFI) %>%
    filter(year == yr) %>%
    filter(if(is_missing) TRUE else week == wk) 
}

Using this on a reprodcuble dataset with mtcars

createTibble <- function(mtcars, i, j) {
    is_missing <- missing(j)
    mtcars %>% filter(am == i) %>% filter(if(is_missing) TRUE else cyl == j)
}

createTibble(mtcars, 1)  

#    mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#4  32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#5  30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#6  33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#7  27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#8  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#9  30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#10 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#11 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#12 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#13 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

createTibble(mtcars, 1, 4) 

#   mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#1 22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#2 32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#3 30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#4 33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#5 27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#6 26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#7 30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#8 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2 

When you use a pipe operator with a conditional evaluation you must use curly brackets around the if or ifelse. Check out Jon Paul's answer on conditional evaluation when using the pipe operator .

I believe the following code is going to work:

    createTibble <- function(i, yr, wk){
  list_sheets[[i]]%>%
    filter(LASTUSER %in% users ) %>% 
    mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
           month = as.numeric(format(DATEMODIFI, format = "%m")),
           week = week(DATEMODIFI),
           day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
    select(-DATEMODIFI) %>%
    {ifelse(missing(wk),filter(year == yr),filter(year == yr) %>% filter(week == wk))} }

I'm not sure about the pipe operator inside the else argument working though. If it doesn't work, you could always try to break the ifelse into two conditions:

createTibble <- function(i, yr, wk){
  list_sheets[[i]]%>%
    filter(LASTUSER %in% users ) %>% 
    mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
           month = as.numeric(format(DATEMODIFI, format = "%m")),
           week = week(DATEMODIFI),
           day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
    select(-DATEMODIFI) %>%
{ifelse(missing(wk),filter(year == yr),.)} %>% 
{if(exists(wk))
filter(week == wk))} }

You are misusing the if_else() function. Its arguments are

if_else(condition, true, false, missing = NULL)

but the first argument you are passing to it is the result of the earlier steps in the pipe, ie

list_sheets[[i]]%>%
filter(LASTUSER %in% users ) %>% 
mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
       month = as.numeric(format(DATEMODIFI, format = "%m")),
       week = week(DATEMODIFI),
       day = as.numeric(format(DATEMODIFI, format = "%d")))%>% 
select(-DATEMODIFI)

Additionally, you really want if , not if_else . So this should work:

list_sheets[[i]]%>%
filter(LASTUSER %in% users ) %>% 
mutate(year = as.numeric(format(DATEMODIFI, format = "%Y")),
       month = as.numeric(format(DATEMODIFI, format = "%m")),
       week = week(DATEMODIFI),
       day = as.numeric(format(DATEMODIFI, format = "%d"))) %>% 
select(-DATEMODIFI) %>%
filter(year == yr) %>% 
if (missing(wk)) . else filter(., week = wk) 

Trying out @RonakShah's example, it does:

library(tidyverse)
createTibble <- function(mtcars, i, j) {
  is_missing <- missing(j)
  mtcars %>% 
    filter(am == i) %>% 
    if (is_missing) . else filter(., cyl == j)
}

createTibble(mtcars, 1) 
#>     mpg cyl  disp  hp drat    wt  qsec vs am gear carb
#> 1  21.0   6 160.0 110 3.90 2.620 16.46  0  1    4    4
#> 2  21.0   6 160.0 110 3.90 2.875 17.02  0  1    4    4
#> 3  22.8   4 108.0  93 3.85 2.320 18.61  1  1    4    1
#> 4  32.4   4  78.7  66 4.08 2.200 19.47  1  1    4    1
#> 5  30.4   4  75.7  52 4.93 1.615 18.52  1  1    4    2
#> 6  33.9   4  71.1  65 4.22 1.835 19.90  1  1    4    1
#> 7  27.3   4  79.0  66 4.08 1.935 18.90  1  1    4    1
#> 8  26.0   4 120.3  91 4.43 2.140 16.70  0  1    5    2
#> 9  30.4   4  95.1 113 3.77 1.513 16.90  1  1    5    2
#> 10 15.8   8 351.0 264 4.22 3.170 14.50  0  1    5    4
#> 11 19.7   6 145.0 175 3.62 2.770 15.50  0  1    5    6
#> 12 15.0   8 301.0 335 3.54 3.570 14.60  0  1    5    8
#> 13 21.4   4 121.0 109 4.11 2.780 18.60  1  1    4    2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM