Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is a command not working in a pipe operator in R, but outside the pipe it works perfectly fine?

Tags:

r

magrittr

My dataframe includes options data. I want to find the closest to the money option for every trading date. Unfortunately

ir_OEX_data %>% group_by(quotedate) %>% which.min(abs(moneyness_call  - 1))

leads to the following error:

Error in which.min(., abs(ir_OEX_data$moneyness_call - 1)) : unused argument (abs(ir_OEX_data$moneyness_call - 1))

But when I run solely:

 which.min(abs(ir_OEX_data$moneyness_call  - 1))

The command works perfectly fine.

What is my mistake here?

like image 879
Chrissss12 Avatar asked Sep 17 '25 11:09

Chrissss12


1 Answers

Problem: not all functions are pipe-friendly

{magrittr} pipes work best with functions written to be "pipe-friendly." These generally take a dataframe as a first argument, and may use data masking to let you refer to columns within that dataframe without prefixing them. e.g., many {dplyr} verbs are pipe-friendly.

which.min isn't pipe-friendly. Your code,

ir_OEX_data %>% group_by(quotedate) %>% which.min(abs(moneyness_call  - 1))

is actually equivalent to

which.min(
  group_by(ir_OEX_data, quotedate), 
  abs(moneyness_call  - 1)
)

but which.min expects only one argument, so throws an error.

Solution 1: the exposition pipe (%$%)

There are a few ways to deal with this. One is the {magrittr} exposition pipe, %$%, which makes your column names available to the next function without passing the data:

library(magrittr)
library(dplyr)

ir_OEX_data %>% 
  group_by(quotedate) %$% 
  which.min(abs(moneyness_call  - 1))

Solution 2: use inside a pipe-friendly function

If you wanted to add the result of which.min to your dataset, you'd just need to use it inside summarize or mutate:

ir_OEX_data %>% 
  group_by(quotedate) %>% 
  summarize(call_which_min = which.min(abs(moneyness_call  - 1)))

Solution 3: write a pipe-friendly wrapper

You can also put a non-friendly function in a pipe-friendly wrapper. This would probably be overkill here, but can be useful in more complex cases.

which_min_pipe <- function(.data, x) {
  .data %>% summarize(out = which.min({{ x }})) %>% pull(out)
}

ir_OEX_data %>% 
  group_by(quotedate) %>% 
  which_min_pipe(abs(moneyness_call - 1))
like image 79
zephryl Avatar answered Sep 20 '25 01:09

zephryl