Home > Mobile >  conditionally copying reference values in r
conditionally copying reference values in r

Time:01-07

I am trying to conditionally copy values from the x column into a new column based on a reference value. for example in row 1, for time == 1, the ref value is 7 so the newx value should copy the x value from time == 1 and id == 7 the copied value always needs to be in the same time block.

In the event the ref value is 0, the newx value should also be 0

I have tried a few approaches and the below is probably the closest I have reached but it still isn't working

        library(dplyr)
        x <- sample(1:50, 24)
        y <- sample(1:50, 24)
        ref <- c(7,7,7,7,0,0,0,0,0,0,0,0,4,3,4,1,8,8,5,8,0,0,0,0)
        id <- rep(seq(1,8,1), 3)
        time <- rep(1:3, each = 8)

    x  y ref id time
1  41 29   7  1    1
2  18 37   7  2    1
3  50 25   7  3    1
4  47  7   7  4    1
5   2 40   0  5    1
6  22 19   0  6    1
7  48  9   0  7    1
8  26 36   0  8    1
9  49 47   0  1    2
10 46 18   0  2    2
11 25 23   0  3    2
12 38  3   0  4    2
13 28 31   4  5    2
14 34  4   3  6    2
15 21 32   4  7    2
16  9 48   1  8    2
17 43 43   8  1    3
18 39 38   8  2    3
19  6 16   5  3    3
20 12 41   8  4    3
21  1 13   0  5    3
22 19 17   0  6    3
23  7 34   0  7    3
24 33 10   0  8    3

        
        df <- as.data.frame(cbind(x,y,ref,id,time))
        
        df <- df %>% group_by(time) %>% mutate(Newx = case_when((ref > 0) ~ x[which(id==ref)],
                                                              T ~ 0,))

CodePudding user response:

You can join df with itself. The last mutate is just to remove the NAs for the ref == 0 rows. You can also use tidyr::replace_na but I wanted to stick to using only dplyr:

df %>%
  left_join(df %>% select(x, id, time) %>% rename(newx = x), by= c("time", "ref" = "id")) %>%
  mutate(newx = ifelse(is.na(newx), 0, newx))

Which results to:

    x  y ref id time newx
1  44 44   7  1    1   36
2  37 26   7  2    1   36
3  40 27   7  3    1   36
4  32 46   7  4    1   36
5  48 33   0  5    1    0
6  31  6   0  6    1    0
7  36  1   0  7    1    0
8  27 11   0  8    1    0
9  26 32   0  1    2    0
10 42 22   0  2    2    0
11 22 21   0  3    2    0
12 15 28   0  4    2    0
13 45 47   4  5    2   15
14 49  4   3  6    2   22
15 25 50   4  7    2   15
16 14  3   1  8    2   26
17 13 42   8  1    3   12
18 38  7   8  2    3   12
19 10 12   5  3    3   50
20  2 40   8  4    3   12
21 50 43   0  5    3    0
22  4  9   0  6    3    0
23 34 49   0  7    3    0
24 12 31   0  8    3    0

CodePudding user response:

Using purrr::map_dbl you could do:

library(purrr)
library(dplyr)

df %>%
  group_by(time) %>%
  mutate(newx = map_dbl(ref, function(ref) if (ref > 0) .data$x[.data$id == ref] else 0)) %>% 
  ungroup()
#> # A tibble: 24 × 6
#>        x     y   ref    id  time  newx
#>    <int> <int> <dbl> <dbl> <int> <dbl>
#>  1    31    17     7     1     1    37
#>  2    15    43     7     2     1    37
#>  3    14    39     7     3     1    37
#>  4     3    12     7     4     1    37
#>  5    42    15     0     5     1     0
#>  6    43    32     0     6     1     0
#>  7    37    42     0     7     1     0
#>  8    48     7     0     8     1     0
#>  9    25     9     0     1     2     0
#> 10    26    41     0     2     2     0
#> # … with 14 more rows

DATA

set.seed(123)

x <- sample(1:50, 24)
y <- sample(1:50, 24)
ref <- c(7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0, 4, 3, 4, 1, 8, 8, 5, 8, 0, 0, 0, 0)
id <- rep(seq(1, 8, 1), 3)
time <- rep(1:3, each = 8)

df <- data.frame(x, y, ref, id, time)
  •  Tags:  
  • Related