I want to add a column to a data.table that is a sequence within groups defined using by, but using a condition on one of the columns used in the by clause. I tried using fifelse as in the following example:
dt <- data.table::data.table(
id = c(1, 1, 2, 2, 2, 3),
clk = c(1, 1, 0, 2, 2, 5),
val = LETTERS[1:6]
)
dt[, seq_clk := fifelse(clk != 0, seq_len(.N), NA_integer_), by = .(id, clk)]
This results in the following error
Error in fifelse(clk != 0, seq_len(.N), NA_integer_) : Length of 'yes' is 2 but must be 1 or length of 'test' (1).
The result I'm expecting to get can be achieved by the following code
dt[, seq_2 := seq_len(.N), by = .(id, clk)][
, seq_clk := fifelse(clk != 0, seq_2, NA_integer_)][
, seq_2 := NULL]
which gives
id clk val seq_clk
1: 1 1 A 1
2: 1 1 B 2
3: 2 0 C NA
4: 2 2 D 1
5: 2 2 E 2
6: 3 5 F 1
Although the above code works, I don't understand why the one-liner in the first example does not work. It seems that the issue is with applying fifelse to a column listed in the by clause. It works fine with columns not in the by.
I've also noticed that other functions do not work as I expect in this situation. For example:
dt[, sum_id_by_clk := fifelse(clk != 0, sum(id), NA_integer_), by = .(id, clk)]
does not give an error, but produces incorrect results:
id clk val sum_id_by_clk
1: 1 1 A 1
2: 1 1 B 1
3: 2 0 C NA
4: 2 2 D 2
5: 2 2 E 2
6: 3 5 F 3
I'd expect the values in the last column to be 2 for rows 1-2 and 4 for rows 4-5.
What am I missing here?