Search code examples
rtidyverse

Shift a cell position based on a number in a column


I have the following data

    hour   day month buy_call_cross_zero sell_call_position
   <dbl> <int> <dbl>               <dbl> <chr>             
 1     9     5     4                   0 NA                
 2    10     5     4                   0 NA                
 3    11     5     4                   0 NA                
 4    12     5     4                   0 NA                
 5    13     5     4                   0 NA                
 6    14     5     4                   0 NA                
 7    15     5     4                   0 NA                
 8    16     5     4                   0 NA                
 9     9     8     4                   2 sell              
10    10     8     4                   0 NA 

In the buy_call_cross_zero column I have a number and in the sell_call_position column I have some word "sell" - in the example above they correspond to 2 and sell. However, in other observations I have the following:

> so[113:120, 1:5]
# A tibble: 8 × 5
# Groups:   day, month [1]
   hour   day month buy_call_cross_zero sell_call_position
  <dbl> <int> <dbl>               <dbl> <chr>             
1     9    25     4                   3 sell              
2    10    25     4                   0 NA                
3    11    25     4                   0 NA                
4    12    25     4                   0 NA                
5    13    25     4                   0 NA                
6    14    25     4                   0 NA                
7    15    25     4                   0 NA                
8    16    25     4                   0 NA  

And also:

> so[153:160, 1:5]
# A tibble: 8 × 5
# Groups:   day, month [1]
   hour   day month buy_call_cross_zero sell_call_position
  <dbl> <int> <dbl>               <dbl> <chr>             
1     9     2     5                   5 sell              
2    10     2     5                   0 NA                
3    11     2     5                   0 NA                
4    12     2     5                   0 NA                
5    13     2     5                   0 NA                
6    14     2     5                   0 NA                
7    15     2     5                   0 NA                
8    16     2     5                   0 NA

What I want to do is shift the sell_call_position observation sell down based on the number in the buy_call_cross_zero column. So in the first example, the expected output would be:

> so[113:120, 1:5]
# A tibble: 8 × 5
# Groups:   day, month [1]
   hour   day month buy_call_cross_zero sell_call_position
  <dbl> <int> <dbl>               <dbl> <chr>             
1     9    25     4                   3 REMOVED              
2    10    25     4                   0 NA                
3    11    25     4                   0 sell                
4    12    25     4                   0 NA                
5    13    25     4                   0 NA                
6    14    25     4                   0 NA                
7    15    25     4                   0 NA                
8    16    25     4                   0 NA  

In the second example, it would be:

> so[153:160, 1:5]
# A tibble: 8 × 5
# Groups:   day, month [1]
   hour   day month buy_call_cross_zero sell_call_position
  <dbl> <int> <dbl>               <dbl> <chr>             
1     9     2     5                   5 REMOVED              
2    10     2     5                   0 NA                
3    11     2     5                   0 NA                
4    12     2     5                   0 NA                
5    13     2     5                   0 sell                
6    14     2     5                   0 NA                
7    15     2     5                   0 NA                
8    16     2     5                   0 NA

Data:

df = structure(list(hour = c(9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16, 9, 10, 
11, 12, 13, 14, 15, 16, 9, 10, 11, 12, 13, 14, 15, 16), day = c(5L, 
5L, 5L, 5L, 5L, 5L, 5L, 5L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 8L, 9L, 
9L, 9L, 9L, 9L, 9L, 9L, 9L, 10L, 10L, 10L, 10L, 10L, 10L, 10L, 
10L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 12L, 
12L, 12L, 12L, 12L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 15L, 16L, 
16L, 16L, 16L, 16L, 16L, 16L, 16L, 17L, 17L, 17L, 17L, 17L, 17L, 
17L, 17L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 18L, 19L, 19L, 19L, 
19L, 19L, 19L, 19L, 19L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 22L, 
23L, 23L, 23L, 23L, 23L, 23L, 23L, 23L, 24L, 24L, 24L, 24L, 24L, 
24L, 24L, 24L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 25L, 26L, 26L, 
26L, 26L, 26L, 26L, 26L, 26L, 29L, 29L, 29L, 29L, 29L, 29L, 29L, 
29L, 30L, 30L, 30L, 30L, 30L, 30L, 30L, 30L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L), month = c(4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
5, 5, 5, 5, 5, 5, 5, 5, 5), buy_call_cross_zero = c(0, 0, 0, 
0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, NA, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), sell_call_position = c("NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "sell", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", NA, "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "sell", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "sell", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"sell", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", "NA", 
"NA", "NA", "NA", "NA", "NA", "NA")), class = c("grouped_df", 
"tbl_df", "tbl", "data.frame"), row.names = c(NA, -168L), groups = structure(list(
    day = c(1L, 2L, 3L, 5L, 8L, 9L, 10L, 11L, 12L, 15L, 16L, 
    17L, 18L, 19L, 22L, 23L, 24L, 25L, 26L, 29L, 30L), month = c(5, 
    5, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
    4), .rows = structure(list(145:152, 153:160, 161:168, 1:8, 
        9:16, 17:24, 25:32, 33:40, 41:48, 49:56, 57:64, 65:72, 
        73:80, 81:88, 89:96, 97:104, 105:112, 113:120, 121:128, 
        129:136, 137:144), ptype = integer(0), class = c("vctrs_list_of", 
    "vctrs_vctr", "list"))), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -21L), .drop = TRUE))

Solution

  • Is this what you are after?

    within(df, {
      idx = which(sell_call_position != "NA") 
      sell_call_position[idx + buy_call_cross_zero[idx]] = sell_call_position[idx]
      sell_call_position[idx] = "REPLACED"
      rm(idx)
    })
    

    gives

        hour day month buy_call_cross_zero sell_call_position
    1      9   5     4                   0                 NA
    2     10   5     4                   0                 NA
    3     11   5     4                   0                 NA
    4     12   5     4                   0                 NA
    5     13   5     4                   0                 NA
    6     14   5     4                   0                 NA
    7     15   5     4                   0                 NA
    8     16   5     4                   0                 NA
    9      9   8     4                   2           REPLACED
    10    10   8     4                   0                 NA
    11    11   8     4                   0               sell
    12    12   8     4                   0                 NA
    13    13   8     4                   0                 NA
    14    14   8     4                   0                 NA
    15    15   8     4                   0                 NA
    16    16   8     4                   0                 NA
    17     9   9     4                  NA               <NA>
    ...
    

    I suggest to re-organise, i.e. standardise, the appearances of "NA", NA, ... in a previous step.