I have a dataframe with one column designated as a group code and 2 other columns containing logical vectors. I want to mutate a new column based on the following conditions:
- The dataframe will first be grouped according to column
x - Get the index of the
TRUEvalues inb - The new column shall contain the index of the nearest TRUE value preceding the
TRUEvalue inb. If there is more than oneTRUEvalue ina, only get the index of the nearestTRUEvalue tob. - The resulting index value will be placed on the same row as the
TRUEvalue inb.
Here's my sample data:
x = rep(c(1:5), each = 10)
a = c(TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE,
FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE)
b = c(FALSE, FALSE, FALSE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE,
FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE, FALSE)
df <- data.frame(x ,a, b)
I have this code that doesn't give the result that I want:
df %>%
group_by(x) %>%
mutate(xx = ifelse(b == TRUE,
which(b)[findInterval(which(a), which(b))],
NA))
My desired output looks like this:
x a b xx
1 1 TRUE FALSE NA
2 1 FALSE FALSE NA
3 1 FALSE FALSE NA
4 1 FALSE TRUE 1
5 1 FALSE FALSE NA
6 1 FALSE FALSE NA
7 1 TRUE FALSE NA
8 1 FALSE FALSE NA
9 1 FALSE FALSE NA
10 1 FALSE TRUE 7
11 2 FALSE FALSE NA
12 2 FALSE FALSE NA
13 2 FALSE FALSE NA
14 2 FALSE FALSE NA
15 2 FALSE FALSE NA
16 2 FALSE FALSE NA
17 2 FALSE FALSE NA
18 2 FALSE TRUE NA
19 2 FALSE FALSE NA
20 2 FALSE FALSE NA
21 3 FALSE FALSE NA
22 3 FALSE FALSE NA
23 3 TRUE FALSE NA
24 3 FALSE FALSE NA
25 3 FALSE FALSE NA
26 3 FALSE FALSE NA
27 3 FALSE FALSE NA
28 3 FALSE FALSE NA
29 3 FALSE FALSE NA
30 3 FALSE FALSE NA
31 4 FALSE FALSE NA
32 4 FALSE FALSE NA
33 4 FALSE FALSE NA
34 4 TRUE FALSE NA
35 4 FALSE FALSE NA
36 4 TRUE FALSE NA
37 4 FALSE FALSE NA
38 4 FALSE FALSE NA
39 4 FALSE TRUE 36
40 4 FALSE FALSE NA
41 5 FALSE FALSE NA
42 5 TRUE FALSE NA
43 5 FALSE FALSE NA
44 5 FALSE FALSE NA
45 5 FALSE FALSE NA
46 5 FALSE FALSE NA
47 5 FALSE FALSE NA
48 5 FALSE FALSE NA
49 5 FALSE TRUE 42
50 5 FALSE FALSE NA
I also thought of converting the dataframe into a list and use a map() but I don't know how to proceed from here...
df %>% split(.$x) %>%
map(~mutate(xx = ifelse(b == TRUE,
which(b)[findInterval(which(a), which(b))],
NA)))