使用三个其他给定变量迭代或按行滚动计算两个联立变量

Rolling computation of two simultaneous variables iteratively or rowwise, using three other given variables

名为 crass 的数据集看起来像 -

> dput(crass)
structure(list(WT_TRADE_PRICE = c(3801, 3801, 3801, 3797, 3797, 
3796.2125, 3800, 3797, 3795.09523809524, 3794, 3793, 3793, 3793.8, 
3794.72, 3793.02777777778, 3789, 3790, 3788, 3788, 3788), min = c(3801, 
3801, 3801, 3797, 3797, 3795, 3800, 3797, 3794, 3794, 3793, 3793, 
3793, 3794, 3790, 3789, 3790, 3788, 3788, 3788), max = c(3801, 
3801, 3801, 3797, 3797, 3800, 3800, 3797, 3797, 3794, 3793, 3793, 
3794, 3797, 3794, 3789, 3790, 3788, 3788, 3788), Bid = c(3801, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA), Ask = c(3802, NA, NA, NA, NA, NA, NA, NA, NA, NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA)), row.names = c(NA, -20L
), class = c("tbl_df", "tbl", "data.frame"))
# A tibble: 20 x 5
   WT_TRADE_PRICE   min   max   Bid   Ask
            <dbl> <dbl> <dbl> <dbl> <dbl>
 1          3801   3801  3801  3801  3802
 2          3801   3801  3801    NA    NA
 3          3801   3801  3801    NA    NA
 4          3797   3797  3797    NA    NA
 5          3797   3797  3797    NA    NA
 6          3796.  3795  3800    NA    NA
 7          3800   3800  3800    NA    NA
 8          3797   3797  3797    NA    NA
 9          3795.  3794  3797    NA    NA
10          3794   3794  3794    NA    NA
11          3793   3793  3793    NA    NA
12          3793   3793  3793    NA    NA
13          3794.  3793  3794    NA    NA
14          3795.  3794  3797    NA    NA
15          3793.  3790  3794    NA    NA
16          3789   3789  3789    NA    NA
17          3790   3790  3790    NA    NA
18          3788   3788  3788    NA    NA
19          3788   3788  3788    NA    NA
20          3788   3788  3788    NA    NA

可以看出,两个变量ask & bid 只有初始值,需要使用以下逻辑迭代填充。

伪代码-

if(WT_TRADE_PRICE >= L(Ask) | WT_TRADE_PRICE > (L(Bid)+L(Ask))/2)
{
  Bid = L(Bid), Ask = max
}
else
{
  Bid = min, Ask = L(Ask)
}

最终输出-

SNo. WT_TRADE_PRICE min max Bid Ask
1 3801 3801 3801 3801 3802
2 3801 3801 3801 3801 3802
3 3801 3801 3801 3801 3802
4 3797 3797 3797 3797 3802
5 3797 3797 3797 3797 3802
6 3796. 3795 3800 3795 3802
7 3800 3800 3800 3795 3800
8 3797 3797 3797 3797 3800
9 3795. 3794 3797 3794 3800
10 3794 3794 3794 3794 3800
11 3793 3793 3793 3793 3800
12 3793 3793 3793 3793 3800
13 3794. 3793 3794 3793 3800
14 3795. 3794 3797 3793 3797
15 3793. 3790 3794 3790 3797
16 3789 3789 3789 3789 3797
17 3790 3790 3790 3790 3797
18 3788 3788 3788 3788 3797
19 3788 3788 3788 3788 3797
20 3788 3788 3788 3788 3797

在这种情况下,我们需要同时生成两个输出列;并在三个输入的帮助下迭代。因此 purrr::accumulate 通常基于一个输入在一个输出上工作,而 purrr::accumulate2() 在 2 个输入上再次工作一个输出。因此,我对 accumulate 的策略如下:-

  • Re-arrange 三个输入列每个输入 row-wise tibbles,因此三列输入中的每一列现在都是一列。为此,我生成了一个虚拟列 id 以便每一行都转换为一个小标题。
  • 我为此使用了 tidyr::nest_by()
  • 对于输出,我再次通过 accumulate 生成了一个 tibble 而不是一个向量。
  • 最后,我使用 tidyr::unnnest_wider()
  • 将两个 tibbles 转换回其原始形状
crass[1:3] %>% 
  nest_by(id = row_number()) %>%
  ungroup() %>%
  mutate(new = accumulate(data, 
                          .init = list(Bid = 3801, Ask = 3802),
                          ~ tibble(Bid = ifelse(.y$WT_TRADE_PRICE >= min(.x$Ask, (.x$Ask + .x$Bid)/2),
                                                     .x$Bid,
                                                     .y$min),
                                        Ask = ifelse(.y$WT_TRADE_PRICE >= min(.x$Ask, (.x$Ask + .x$Bid)/2),
                                                     .y$max,
                                                     .x$Ask))
                          )[-1]) %>%
  unnest_wider(data) %>%
  unnest_wider(new)

# A tibble: 20 x 6
      id WT_TRADE_PRICE   min   max   Bid   Ask
   <int>          <dbl> <dbl> <dbl> <dbl> <dbl>
 1     1          3801   3801  3801  3801  3802
 2     2          3801   3801  3801  3801  3802
 3     3          3801   3801  3801  3801  3802
 4     4          3797   3797  3797  3797  3802
 5     5          3797   3797  3797  3797  3802
 6     6          3796.  3795  3800  3795  3802
 7     7          3800   3800  3800  3795  3800
 8     8          3797   3797  3797  3797  3800
 9     9          3795.  3794  3797  3794  3800
10    10          3794   3794  3794  3794  3800
11    11          3793   3793  3793  3793  3800
12    12          3793   3793  3793  3793  3800
13    13          3794.  3793  3794  3793  3800
14    14          3795.  3794  3797  3794  3800
15    15          3793.  3790  3794  3790  3800
16    16          3789   3789  3789  3789  3800
17    17          3790   3790  3790  3790  3800
18    18          3788   3788  3788  3788  3800
19    19          3788   3788  3788  3788  3800
20    20          3788   3788  3788  3788  3800

之前修改过for循环

语法


for(i in 2:nrow(crass)){
    if(crass[i, 1] >= min(crass[i-1, 5], (crass[i-1, 4] + crass[i-1, 5])/2)){
    crass[i, 5] <- crass[i, 3]
    crass[i, 4] <- crass[i-1, 4]
  } else {
    crass[i, 4] <- crass[i, 2]
    crass[i, 5] <- crass[i-1, 5]
  } 
}

crass
# A tibble: 20 x 5
   WT_TRADE_PRICE   min   max   Bid   Ask
            <dbl> <dbl> <dbl> <dbl> <dbl>
 1          3801   3801  3801  3801  3802
 2          3801   3801  3801  3801  3802
 3          3801   3801  3801  3801  3802
 4          3797   3797  3797  3797  3802
 5          3797   3797  3797  3797  3802
 6          3796.  3795  3800  3795  3802
 7          3800   3800  3800  3795  3800
 8          3797   3797  3797  3797  3800
 9          3795.  3794  3797  3794  3800
10          3794   3794  3794  3794  3800
11          3793   3793  3793  3793  3800
12          3793   3793  3793  3793  3800
13          3794.  3793  3794  3793  3800
14          3795.  3794  3797  3794  3800
15          3793.  3790  3794  3790  3800
16          3789   3789  3789  3789  3800
17          3790   3790  3790  3790  3800
18          3788   3788  3788  3788  3800
19          3788   3788  3788  3788  3800
20          3788   3788  3788  3788  3800

crass for循环运行之前

# A tibble: 20 x 5
   WT_TRADE_PRICE   min   max   Bid   Ask
            <dbl> <dbl> <dbl> <dbl> <dbl>
 1          3801   3801  3801  3801  3802
 2          3801   3801  3801    NA    NA
 3          3801   3801  3801    NA    NA
 4          3797   3797  3797    NA    NA
 5          3797   3797  3797    NA    NA
 6          3796.  3795  3800    NA    NA
 7          3800   3800  3800    NA    NA
 8          3797   3797  3797    NA    NA
 9          3795.  3794  3797    NA    NA
10          3794   3794  3794    NA    NA
11          3793   3793  3793    NA    NA
12          3793   3793  3793    NA    NA
13          3794.  3793  3794    NA    NA
14          3795.  3794  3797    NA    NA
15          3793.  3790  3794    NA    NA
16          3789   3789  3789    NA    NA
17          3790   3790  3790    NA    NA
18          3788   3788  3788    NA    NA
19          3788   3788  3788    NA    NA
20          3788   3788  3788    NA    NA

您还可以在 base R 中使用以下解决方案。 对于此解决方案,我使用行号作为要在 Reduce 中使用的主要向量。我们可以在有多个输出变量的情况下使用这种技术。应该注意的是,为了区分 BidAsk 的先前值,我使用了双括号来对所需值进行子集化。

cbind(crass[1:3], 
      do.call(rbind, Reduce(function(x, y) {
        data.frame(Bid = ifelse(crass$WT_TRADE_PRICE[y] >= min(x[["Ask"]], (x[["Ask"]] + x[["Bid"]])/2),
                                x[["Bid"]],
                                crass$min[y]),
                   Ask = ifelse(crass$WT_TRADE_PRICE[y] >= min(x[["Ask"]], (x[["Ask"]] + x[["Bid"]])/2),
                                crass$max[y],
                                x[["Ask"]]))
      }, init = data.frame(Bid = crass$Bid[1],
                           Ask = crass$Ask[1]),
      seq_len(nrow(crass))[-1], accumulate = TRUE)))

结果

   WT_TRADE_PRICE  min  max  Bid  Ask
1        3801.000 3801 3801 3801 3802
2        3801.000 3801 3801 3801 3802
3        3801.000 3801 3801 3801 3802
4        3797.000 3797 3797 3797 3802
5        3797.000 3797 3797 3797 3802
6        3796.213 3795 3800 3795 3802
7        3800.000 3800 3800 3795 3800
8        3797.000 3797 3797 3797 3800
9        3795.095 3794 3797 3794 3800
10       3794.000 3794 3794 3794 3800
11       3793.000 3793 3793 3793 3800
12       3793.000 3793 3793 3793 3800
13       3793.800 3793 3794 3793 3800
14       3794.720 3794 3797 3794 3800
15       3793.028 3790 3794 3790 3800
16       3789.000 3789 3789 3789 3800
17       3790.000 3790 3790 3790 3800
18       3788.000 3788 3788 3788 3800
19       3788.000 3788 3788 3788 3800
20       3788.000 3788 3788 3788 3800