options(microbenchmark.unit = "us")Usage
n_vars <- 10
n_obs <- 1000
weights <- 0.9 ^ (n_obs:1)
x <- matrix(rnorm(n_obs * n_vars), nrow = n_obs, ncol = n_vars)
y <- matrix(rnorm(n_obs), nrow = n_obs, ncol = 1)
x_lgl <- x < 0Rolling any
result <- microbenchmark::microbenchmark(
"125" = roll::roll_any(x_lgl, width = 125, min_obs = 1),
"250" = roll::roll_any(x_lgl, width = 250, min_obs = 1),
"500" = roll::roll_any(x_lgl, width = 500, min_obs = 1),
"1000" = roll::roll_any(x_lgl, width = 1000, min_obs = 1)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 122.1 139.45 150.118 143.70 156.30 322.3 100
250 131.0 138.35 885.063 148.20 162.15 73523.7 100
500 128.6 135.25 149.147 143.65 160.35 191.1 100
1000 120.3 127.70 143.784 134.30 156.20 367.0 100
Rolling all
result <- microbenchmark::microbenchmark(
"125" = roll::roll_all(x_lgl, width = 125, min_obs = 1),
"250" = roll::roll_all(x_lgl, width = 250, min_obs = 1),
"500" = roll::roll_all(x_lgl, width = 500, min_obs = 1),
"1000" = roll::roll_all(x_lgl, width = 1000, min_obs = 1)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 82.4 90.15 114.051 94.70 134.00 228.1 100
250 80.6 88.95 110.066 94.95 134.35 216.0 100
500 75.7 85.60 108.501 89.40 135.15 292.7 100
1000 72.8 78.70 94.912 82.30 106.70 181.8 100
Rolling sums
\[ \begin{aligned} &\text{Expanding window} \\ &\bullet\text{sum}_{x}\leftarrow\lambda\times\text{sum}_{x}+\text{w}_{new}\times\text{x}_{new}\\ &\text{Rolling window}\\ &\bullet\text{sum}_{x}\leftarrow\lambda\times\text{sum}_{x}+\text{w}_{new}\times\text{x}_{new}-\lambda\times\text{w}_{old}\times\text{x}_{old} \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_sum(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_sum(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_sum(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_sum(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 95.5 107.60 127.335 114.25 130.00 278.5 100
250 94.2 106.95 130.752 113.75 136.90 328.1 100
500 95.3 106.80 132.233 117.80 148.15 296.6 100
1000 91.6 101.80 127.463 109.20 138.10 291.1 100
Rolling products
\[ \begin{aligned} &\text{Expanding window}\\ &\bullet\text{prod}_{w}\leftarrow\text{prod}_{w}\times\text{w}_{new}\\ &\bullet\text{prod}_{x}\leftarrow\text{prod}_{x}\times\text{x}_{new}\\ &\text{Rolling window}\\ &\bullet\text{prod}_{x}\leftarrow\text{prod}_{x}\times\text{x}_{new}/\text{x}_{old} \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_prod(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_prod(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_prod(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_prod(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 207.2 219.7 236.949 228.60 241.55 374.9 100
250 207.8 224.7 240.577 236.35 247.40 350.6 100
500 136.6 154.1 175.491 165.55 180.55 388.8 100
1000 135.6 155.0 178.438 165.30 176.85 557.2 100
Rolling means
\[ \begin{aligned} &\text{Expanding window}\\ &\bullet\text{sum}_{w}\leftarrow\text{sum}_{w}+\text{w}_{new}\\ &\bullet\text{sum}_{x}\leftarrow\lambda\times\text{sum}_{x}+\text{w}_{new}\times\text{x}_{new}\\ &\text{Rolling window}\\ &\bullet\text{sum}_{x}\leftarrow\lambda\times\text{sum}_{x}+\text{w}_{new}\times\text{x}_{new}-\lambda\times\text{w}_{old}\times \text{x}_{old} \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_mean(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_mean(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_mean(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_mean(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 99.3 107.25 133.575 113.50 147.65 305.0 100
250 101.8 109.90 134.233 115.55 149.90 268.7 100
500 99.2 106.25 128.771 112.30 143.80 246.4 100
1000 96.5 102.70 129.033 115.45 143.80 217.0 100
Rolling minimums
result <- microbenchmark::microbenchmark(
"125" = roll::roll_min(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_min(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_min(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_min(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 131.5 147.0 167.555 154.40 180.05 268.4 100
250 117.8 145.8 163.208 154.75 167.00 304.5 100
500 139.9 149.8 173.730 159.40 184.25 366.6 100
1000 134.7 147.1 181.030 162.50 194.20 911.0 100
Rolling maximums
result <- microbenchmark::microbenchmark(
"125" = roll::roll_max(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_max(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_max(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_max(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 102.6 115.70 131.797 123.20 134.20 233.4 100
250 101.7 114.05 136.393 122.15 137.10 256.8 100
500 105.0 113.95 133.193 121.95 135.75 332.2 100
1000 101.4 111.05 130.468 117.40 136.45 261.7 100
Rolling index of minimums
result <- microbenchmark::microbenchmark(
"125" = roll::roll_idxmin(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_idxmin(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_idxmin(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_idxmin(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 101.0 116.00 132.410 130.55 142.85 301.5 100
250 106.5 120.05 138.459 132.95 148.00 320.5 100
500 98.8 119.50 136.189 133.15 144.40 333.5 100
1000 97.2 116.05 131.241 128.35 141.80 194.9 100
Rolling index of maximums
result <- microbenchmark::microbenchmark(
"125" = roll::roll_idxmax(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_idxmax(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_idxmax(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_idxmax(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 103.2 111.45 129.493 118.15 137.95 241.2 100
250 100.1 111.30 130.007 116.80 132.60 274.4 100
500 103.8 111.30 130.981 117.00 134.80 346.0 100
1000 97.0 110.70 133.250 117.05 148.35 274.4 100
Rolling medians
# "'online' is only supported for equal 'weights'"
result <- microbenchmark::microbenchmark(
"125" = roll::roll_median(x, width = 125, min_obs = 1),
"250" = roll::roll_median(x, width = 250, min_obs = 1),
"500" = roll::roll_median(x, width = 500, min_obs = 1),
"1000" = roll::roll_median(x, width = 1000, min_obs = 1)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 746.3 807.45 910.488 832.10 866.85 7271.2 100
250 740.6 810.15 851.863 834.15 924.65 963.7 100
500 679.8 735.50 800.554 761.80 790.10 3382.7 100
1000 518.2 566.25 598.112 589.10 610.20 1407.7 100
Rolling quantiles
# "'online' is only supported for equal 'weights'"
result <- microbenchmark::microbenchmark(
"125" = roll::roll_quantile(x, width = 125, min_obs = 1),
"250" = roll::roll_quantile(x, width = 250, min_obs = 1),
"500" = roll::roll_quantile(x, width = 500, min_obs = 1),
"1000" = roll::roll_quantile(x, width = 1000, min_obs = 1)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 788.7 820.50 849.449 834.00 845.80 1378.2 100
250 779.8 806.10 829.049 821.20 837.90 1052.1 100
500 728.5 751.65 774.702 766.60 783.90 1007.6 100
1000 552.5 583.80 604.054 598.05 612.75 783.1 100
Rolling variances
\[ \begin{aligned} &\text{Expanding window}\\ &\bullet\text{sum}_{w}\leftarrow\text{sum}_{w}+\text{w}_{new}\\ &\bullet\text{sumsq}_{w}\leftarrow\text{sumsq}_{w}+\text{w}_{new}^{2}\\ &\bullet\text{sumsq}_{x}\leftarrow\lambda\times\text{sumsq}_{x}+\text{w}_{new}\times (\text{x}_{new}-\text{mean}_{x})(\text{x}_{new}-\text{mean}_{prev_x})\\ &\text{Rolling window}\\ &\bullet\text{sumsq}_{x}\leftarrow\lambda\times\text{sumsq}_{x}+\text{w}_{new}\times (\text{x}_{new}-\text{mean}_{x})(\text{x}_{new}-\text{mean}_{prev_x})-\\ &\lambda\times\text{w}_{old}\times (\text{x}_{old}-\text{mean}_{x})(\text{x}_{old}-\text{mean}_{prev_x}) \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_var(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_var(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_var(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_var(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 118.9 137.50 154.914 147.30 156.65 290.7 100
250 117.5 135.75 151.086 148.65 155.30 298.6 100
500 120.0 132.40 150.285 143.05 151.80 373.9 100
1000 108.1 125.20 138.725 134.70 143.15 275.0 100
Rolling standard deviations
result <- microbenchmark::microbenchmark(
"125" = roll::roll_sd(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_sd(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_sd(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_sd(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 122.1 142.80 161.970 153.45 164.25 326.4 100
250 132.7 141.90 160.125 151.60 165.45 296.8 100
500 129.9 137.45 152.858 146.75 158.05 313.0 100
1000 109.0 132.35 156.075 142.70 159.25 406.1 100
Rolling scaling and centering
result <- microbenchmark::microbenchmark(
"125" = roll::roll_scale(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_scale(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_scale(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_scale(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 145.1 152.90 178.613 164.30 191.1 569.6 100
250 145.1 150.90 176.003 159.40 178.7 642.6 100
500 141.7 148.50 173.040 162.25 190.2 351.5 100
1000 135.0 141.05 161.846 154.95 168.9 280.1 100
Rolling covariances
\[ \begin{aligned} &\text{Expanding window}\\ &\bullet\text{sum}_{w}\leftarrow\text{sum}_{w}+\text{w}_{new}\\ &\bullet\text{sumsq}_{w}\leftarrow\text{sumsq}_{w}+\text{w}_{new}^{2}\\ &\bullet\text{sumsq}_{xy}\leftarrow\lambda\times\text{sumsq}_{xy}+\text{w}_{new}\times (\text{x}_{new}-\text{mean}_{x})(\text{y}_{new}-\text{mean}_{prev_y})\\ &\text{Rolling window}\\ &\bullet\text{sumsq}_{xy}\leftarrow\lambda\times\text{sumsq}_{xy}+\text{w}_{new}\times (\text{x}_{new}-\text{mean}_{x})(\text{y}_{new}-\text{mean}_{prev_y})-\\ &\lambda\times\text{w}_{old}\times (\text{x}_{old}-\text{mean}_{x})(\text{y}_{old}-\text{mean}_{prev_y}) \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_cov(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_cov(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_cov(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_cov(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 742.8 911.80 1038.197 972.50 1036.05 7535.8 100
250 672.6 855.65 1017.200 935.00 1020.50 6087.4 100
500 653.2 836.15 956.936 905.35 969.30 6041.5 100
1000 564.3 732.95 823.702 762.20 813.55 6017.8 100
Rolling correlations
result <- microbenchmark::microbenchmark(
"125" = roll::roll_cor(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_cor(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_cor(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_cor(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 861.5 1029.60 1078.781 1077.90 1126.75 1490.8 100
250 774.2 980.30 1126.301 1064.40 1147.30 4535.5 100
500 739.7 895.50 1000.387 974.70 1042.45 4175.1 100
1000 641.4 772.45 909.451 828.05 865.25 4145.3 100
Rolling crossproducts
result <- microbenchmark::microbenchmark(
"125" = roll::roll_crossprod(x, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_crossprod(x, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_crossprod(x, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_crossprod(x, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 551.4 624.5 678.036 675.05 711.45 1168.1 100
250 547.9 605.9 755.236 659.45 717.90 3993.3 100
500 531.5 579.8 737.054 635.25 680.05 3927.9 100
1000 501.6 537.8 623.640 562.30 618.70 3822.3 100
Rolling linear models
\[ \begin{aligned} &\text{coef}=\text{cov}_{xx}^{-1}\times\text{cov}_{xy}\\ &\text{intercept}=\text{mean}_{y}-\text{coef}\times\text{mean}_{x}\\ &\text{rsq}=\frac{\text{coef}^{T}\times\text{cov}_{xx}\times\text{coef}}{\text{var}_{y}}\\ &\text{var}_{resid}=\frac{(1-\text{rsq})(\text{var}_{y})(\text{sum}_{w}-\text{sumsq}_{w}/\text{sum}_{w})}{\text{n}_{rows}-\text{n}_{cols}}\\ &\text{xx}=\text{cov}_{xx}\times(\text{sum}_{w}-\text{sumsq}_{w}/\text{sum}_{w})\\ &\text{se}_{coef}=\sqrt{\text{var}_{resid}\times\text{diag}(\text{xx}^{-1})}\\ &\text{se}_{intercept}=\sqrt{\text{var}_{resid}\left(1/\text{sum}_{w}+\text{mean}_{x}^{T}\text{xx}^{-1}\text{mean}_{x}\right)} \end{aligned} \]
result <- microbenchmark::microbenchmark(
"125" = roll::roll_lm(x, y, width = 125, min_obs = 1, weights = weights),
"250" = roll::roll_lm(x, y, width = 250, min_obs = 1, weights = weights),
"500" = roll::roll_lm(x, y, width = 500, min_obs = 1, weights = weights),
"1000" = roll::roll_lm(x, y, width = 1000, min_obs = 1, weights = weights)
)
print(result)Unit: microseconds
expr min lq mean median uq max neval
125 2140.9 2342.15 2510.482 2432.95 2549.65 4350.2 100
250 2078.6 2328.70 2521.667 2442.40 2631.50 3821.7 100
500 2092.6 2276.50 2448.099 2384.40 2523.95 3547.1 100
1000 2030.9 2235.15 2496.523 2331.20 2457.30 6381.6 100
References
- Weights: https://stackoverflow.com/a/9933794
- Index: https://stackoverflow.com/a/11316626
- Index: https://stackoverflow.com/a/34363187
- Index: https://stackoverflow.com/a/243342
- Quantile (comparator): https://stackoverflow.com/a/51992954
- Quantile (comparator): https://stackoverflow.com/a/25921772
- Quantile (comparator): https://stackoverflow.com/a/40416506
- Median: https://stackoverflow.com/a/5970314
- Median: https://stackoverflow.com/a/5971248
- Median: https://gist.github.com/ashelly/5665911
- Standard errors: https://stats.stackexchange.com/a/64217