Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R: dplyr pipe conditional lead/lag using ifelse with unexpected behavior

I'm trying to use a conditional lead/lag function in a dplyr pipe using ifelse but getting an error. However, using the same approach outside the pipe it seems to work. What am I missing?

require(dplyr)

Data:

test <- data.frame(a = c("b","b","b","b","b","b",
                         "m","m","m","m","m","m",
                         "s","s","s","s","s","s"), 
                   b = replicate(1,n=18), 
                   stringsAsFactors=F)

dplyr pipe:

test %>%
  mutate(delta = ifelse(a == "s", b + lag(b, n = 2*6),
                        ifelse(a == "m", b + lag(b, n = 1*6), 0)))

# Error: could not convert second argument to an integer. type=LANGSXP, length = 3

Without the pipe it works:

test$delta <- ifelse(test$a == "s", test$b + lag(test$b, n = 2*6),
                     ifelse(test$a == "m", test$b + lag(test$b, n = 1*6), 0))

I found some indication that there was an issue with dplyr lead/lag in combination with grouped data frames. But I am not grouping here.

Version info: R 3.1.1 and dplyr_0.4.1.

like image 481
Triamus Avatar asked Apr 23 '15 08:04

Triamus


2 Answers

This:

test %>%
    mutate(delta = ifelse(a=="s",b+lag(b,n=12),
                          ifelse(a=="m",b+lag(b,n=6),0)))

works. This means that you cannot pass expressions in lag arguments.

like image 82
mpiktas Avatar answered Oct 18 '22 22:10

mpiktas


dplyr fails to parse the expression. One solution is to define the function first:

foo <- function(a, b)
    ifelse(a=="s",b+lag(b,n=2*6), ifelse(a=="m",b+lag(b,n=1*6),0))
test %>% mutate(delta = foo(a,b))
like image 41
Randy Lai Avatar answered Oct 18 '22 20:10

Randy Lai