Q:

lag function in ifelse

I have a dataframe df with a structure like this:
val1 val2 val3
1    12   NA
2    14   NA
3    54   54
1    35   4
2    3    5
3    7    NA
4    8    NA
5    9    NA

Expected value:
val1 val2 val3  val4
1    12   NA    12
2    14   NA    12
3    54   54    54
1    35   4     35
2    3    5     3
3    7    NA    3
4    8    NA    3
5    9    NA    3

Problem:
I need a new column val4 with the following condition
df$val4 <- ifelse(df$val1 == 1, df$val2, ifelse(is.na(df$val3), lag(df$val4), df$val2))

This leads to 
Error in hasTsp(x) : attempt to set an attribute on NULL

Condition:

val4 is equal to value of val2 when val1 is equal 1 (val3 does not matter)
val4 is equal to previous value when val3 is NA ( expect when val1 is not equal to 1)

P.S: I know I can use for loop here, but that would be very slow! 

A:

We can use data.table with zoo.  Convert the 'data.frame' to 'data.table' (setDT(df)), create the 'val4' by multiplying the 'val2' with a vector of 1's and NA (NA^is.na(val3) - returns NA for NA elements in 'val3' while the non-NA is changed to 1), then for 1 in 'val1', we assign 'val4' to 'val2', and replace the NA elements with the previous non-NA elements with na.locf
library(data.table)
library(zoo)
setDT(df)[, val4 := val2 * NA^is.na(val3)
         ][val1==1, val4 := val2
          ][, val4 := na.locf(val4)][]
#   val1 val2 val3 val4
#1:    1   12   NA   12
#2:    2   14   NA   12
#3:    3   54   54   54
#4:    1   35    4   35
#5:    2    3    5    3
#6:    3    7   NA    3
#7:    4    8   NA    3
#8:    5    9   NA    3

More code explanation
`is.na` returns a `logical` vector

setDT(df)[, is.na(val3)]
#[1]  TRUE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE

If we need to change the TRUE values to NA and 1 to others
setDT(df)[, NA^is.na(val3)]
#[1] NA NA  1  1  1 NA NA NA

Multiply by 'val2'
setDT(df)[, val2 * NA^is.na(val3)]
#[1] NA NA 54 35  3 NA NA NA

and the rest is just assignment based on the logical condition in 'i'
data
df <- structure(list(val1 = c(1L, 2L, 3L, 1L, 2L, 3L, 4L, 5L), val2 = c(12L, 
14L, 54L, 35L, 3L, 7L, 8L, 9L), val3 = c(NA, NA, 54L, 4L, 5L, 
NA, NA, NA)), .Names = c("val1", "val2", "val3"), class = "data.frame", 
row.names = c(NA, -8L))

