【问题标题】:Rolling computation of two simultaneous variables iteratively or rowwise, using three other given variables使用其他三个给定变量迭代或逐行滚动计算两个同时变量
【发布时间】:2021-06-21 13:08:53
【问题描述】:

名为 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 两个变量只有初始值,需要使用以下逻辑迭代填充。

  • 如果WT_TRDAE_PRICE&gt;=Ask 的先前值OR WT_TRADE_PRICE 将检查&gt; 是否比先前bidask 的平均值-然后当前ask 将设置为等于当前行 max 变量,bid 将设置为等于先前的 bid 值。
  • 否则,当前的ask 将设置为之前的ask 值和bid 设置为max

伪代码-

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

【问题讨论】:

  • 我认为你的输入 dput 和表输入值是不同的。你能纠正吗
  • crass %&gt;% mutate(Bid = min, Prev_Bid = lag(Bid)) 这给出了预期的输出。可能是一个更好的例子会让它更清楚
  • 简化您的条件
  • @akrun,在您的空闲时间请看这个问题。由于accumulate2 最多可以处理两个变量,因此我将三个变量分别转换为一行小标题,并使用accumulate 生成两个同时变量。但我相信您可以在需要将超过 2 个变量传递到 accumulate 的情况下提供一些替代策略,因为我们没有 paccumulate 有点东西
  • @AnilGoyal 我会使用for 循环,因为它具有更大的灵活性

标签: r dplyr iteration rolling-computation accumulate


【解决方案1】:

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

  • 将三个输入列重新排列为每一个按行排列的 tibbles,这样三列输入中的每一个现在都是一列。为此,我生成了一个虚拟列 id,以便每一行都转换为一个 tibble。
  • 我为此使用了tidyr::nest_by()
  • 对于输出,我再次通过累积生成了一个 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

【讨论】:

  • 在第 13 行,wt_trade_price = 3794 大于 L(Bid) ~ 3793。还有 wt_trade_price
  • 循环中的小修正。我仍然可以在第 14 行看到一些问题。WT (3795) > L(Bid) 即 3793 并且低于 3973 和 3800 (3796.5) 的平均值,那么第 14 行的出价应该是 3794 并且要价应该是 3800。请重新-检查
  • 这个过程很好,但是太慢了——数据集有 300 万行。任何矢量化解决方案?
  • @shoonya,你检查过矢量化解决方案
【解决方案2】:

您还可以在基础 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

【讨论】:

    猜你喜欢
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-26
    • 2021-02-10
    • 2021-03-31
    • 2021-06-21
    相关资源
    最近更新 更多