Chances are, some of the groups have nothing but NAs for earnann. When ifelse isn't given any non-NA values for the test parameter, it will return a logical vector.
Example:
ifelse(NA, 1L, 0L)
# [1] NA
class(ifelse(NA, 1L, 0L))
# [1] "logical"
class(ifelse(c(TRUE, NA), 1L, 0L))
# [1] "integer"
To be truly safe with ifelse, either explicitly coerce the value:
sample_final1[
,':='(earnann1 = as.integer(ifelse(shift(earnann, 1L, type = "lead") == 1L, 1L, 0L))),
by = secid
]
or use dplyr's if_else function, which is strict about the returned value's type.
sample_final1[
,':='(earnann1 = dplyr::if_else(shift(earnann, 1L, type = "lead") == 1L, 1L, 0L)),
by = secid
]
This has nothing to do with your question, but may I ask why you're using 1L and 0L? If you just want to flag rows as true or false, you could use a logical vector.
sample_final1[
, ':=' (earnann = is.na(datadate)), by = secid
][
, ':='(
earnann1 = shift(earnann, 1L, type = "lead"),
earnann2 = shift(earnann, 1L, type = "lead") | shift(earnann, 2L, type = "lead"),
earnann3 = shift(earnann, 1L, type = "lead") | shift(earnann, 2L, type = "lead") | shift(earnann, 3L, type = "lead")
),
by = secid
]