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 169.6 237.0 265.438 255.80 286.15 426.8 100
250 175.0 233.5 1214.944 255.85 283.30 95219.4 100
500 166.4 213.4 246.517 233.95 263.10 507.9 100
1000 152.5 210.3 239.109 234.90 264.75 350.8 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 121.8 220.10 264.719 254.75 300.80 587.3 100
250 156.0 224.35 272.212 257.10 303.35 637.0 100
500 117.4 213.75 256.065 241.15 285.00 727.3 100
1000 163.9 197.65 240.048 229.10 265.70 687.2 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 139.1 203.00 240.811 239.25 266.50 401.5 100
250 157.9 211.80 260.370 245.15 293.95 479.2 100
500 145.1 206.90 250.757 238.50 279.60 740.6 100
1000 151.0 196.95 247.057 231.35 273.95 537.6 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 316.1 377.1 438.589 413.45 469.50 911.9 100
250 297.5 369.4 440.955 402.85 490.65 723.5 100
500 193.9 257.2 307.931 293.45 336.30 664.3 100
1000 207.1 258.8 314.956 300.50 364.70 623.4 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 153.4 195.85 231.694 223.95 260.80 379.4 100
250 152.2 197.55 241.089 233.00 277.80 466.5 100
500 142.0 196.60 242.061 239.80 273.25 460.7 100
1000 161.1 198.60 239.121 217.70 263.25 581.7 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 180.8 227.95 265.547 258.7 299.70 440.0 100
250 169.1 216.45 253.690 251.5 284.15 395.2 100
500 181.6 222.25 269.239 250.8 303.85 494.3 100
1000 177.2 226.95 261.888 260.4 287.25 398.1 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 204.5 252.15 283.285 271.45 300.70 518.4 100
250 204.0 255.65 294.771 284.55 317.40 617.3 100
500 197.5 257.25 295.003 284.00 320.35 490.3 100
1000 210.8 249.65 293.701 287.90 319.85 520.0 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 157.1 213.70 245.118 241.35 274.35 369.2 100
250 153.5 207.30 239.541 235.00 262.05 356.0 100
500 159.7 217.95 246.032 241.45 268.10 458.3 100
1000 149.2 213.00 246.664 233.85 265.40 479.0 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 169.9 219.6 253.905 251.90 277.70 635.6 100
250 166.5 220.2 257.903 253.45 283.05 589.4 100
500 165.0 204.0 246.169 235.35 273.55 538.5 100
1000 175.2 216.2 252.060 246.55 281.95 393.1 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 1015.7 1407.55 1510.976 1460.65 1571.50 2991.3 100
250 944.8 1407.90 1602.424 1496.05 1594.20 9238.9 100
500 1179.0 1292.25 1445.453 1386.75 1466.20 4604.7 100
1000 908.3 989.35 1130.926 1069.65 1200.85 2500.1 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 1234.9 1385.45 1493.890 1458.15 1565.30 2304.0 100
250 1232.2 1362.25 1480.285 1448.05 1542.70 2414.7 100
500 1113.8 1263.60 1377.638 1320.20 1422.50 2247.9 100
1000 868.9 983.95 1076.049 1034.45 1111.45 1899.6 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 179.9 228.20 267.682 264.65 299.20 393.6 100
250 182.2 220.55 269.527 264.30 296.70 666.5 100
500 167.5 212.90 256.175 248.95 283.80 507.4 100
1000 165.5 208.65 244.637 236.60 265.05 396.4 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 179.2 239.00 288.371 283.35 322.70 599.1 100
250 180.2 229.35 264.676 258.85 293.65 604.2 100
500 190.0 233.55 269.849 269.65 294.35 622.2 100
1000 171.7 219.75 258.615 254.00 291.25 494.3 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 204.6 242.80 291.714 282.55 326.45 443.6 100
250 216.2 246.30 280.026 273.35 297.00 471.9 100
500 198.4 234.40 283.826 272.90 322.70 446.9 100
1000 183.0 229.25 274.412 268.00 297.60 670.8 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 1138.0 1395.40 1616.938 1512.00 1622.00 8713.2 100
250 1060.6 1325.70 1589.562 1427.30 1576.75 9154.4 100
500 1030.7 1260.25 1471.899 1371.75 1487.80 10952.9 100
1000 885.6 1102.10 1280.072 1218.10 1310.90 7998.7 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 1118.0 1573.40 1933.720 1769.45 1925.6 7065.3 100
250 1134.5 1577.05 1807.487 1704.25 1842.4 8204.9 100
500 1137.4 1434.05 1592.441 1553.50 1723.4 2764.2 100
1000 921.1 1232.00 1333.853 1340.35 1424.5 1734.0 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 836.2 1013.25 1167.567 1103.1 1191.20 6366.2 100
250 720.5 1014.70 1172.648 1106.0 1203.65 5342.8 100
500 674.6 912.40 1132.177 1044.5 1134.85 6861.3 100
1000 626.5 869.15 963.815 959.9 1056.70 1301.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 3870.5 4477.65 4889.767 4832.80 5240.55 6851.2 100
250 3473.9 4511.85 4986.355 4749.55 5225.55 14647.6 100
500 3341.3 4304.60 4765.339 4646.40 5023.50 10687.0 100
1000 3168.7 4237.00 4576.689 4555.70 4894.95 6243.3 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