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 155.1 160.75 178.546 169.50 188.85 251.3 100
250 151.1 157.90 181.832 171.05 198.55 273.5 100
500 148.6 155.25 170.292 162.55 181.75 245.3 100
1000 137.8 144.15 11811.606 149.55 168.80 1165656.3 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 90.4 115.25 135.149 126.35 156.45 235.8 100
250 93.2 111.10 139.593 121.65 162.80 301.0 100
500 86.0 102.80 130.102 114.60 154.80 265.2 100
1000 83.2 91.35 112.524 98.20 130.10 201.3 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 122.4 131.55 150.605 138.90 156.80 287.0 100
250 123.7 132.45 157.192 142.90 160.15 338.1 100
500 122.2 131.25 155.520 142.60 157.00 306.7 100
1000 117.4 128.40 151.627 138.45 161.00 312.8 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 379.8 429.35 454.423 446.70 474.65 723.1 100
250 388.3 435.70 465.079 454.55 475.65 698.4 100
500 278.5 310.90 330.266 320.00 346.60 428.6 100
1000 269.8 306.65 328.519 321.75 345.05 442.3 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 118.1 144.50 170.106 160.65 190.85 281.1 100
250 128.6 138.85 171.829 164.85 187.45 299.9 100
500 114.5 143.80 172.549 163.50 188.60 342.9 100
1000 120.8 136.20 167.034 155.70 182.80 385.3 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 135.2 143.50 158.469 148.45 170.75 233.0 100
250 136.0 145.40 168.808 150.40 175.90 367.4 100
500 128.8 144.55 168.441 152.60 182.05 288.1 100
1000 134.7 143.80 168.930 156.80 187.55 270.2 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 137.1 142.00 156.701 146.00 154.1 245.3 100
250 136.9 143.05 162.369 149.75 172.6 270.7 100
500 137.4 141.30 159.029 146.75 167.1 354.1 100
1000 133.5 140.10 164.789 145.45 189.0 263.4 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 135.3 155.15 174.544 166.40 185.60 294.1 100
250 135.9 155.45 176.195 165.40 196.05 265.4 100
500 135.4 150.90 175.207 161.55 192.60 384.1 100
1000 135.3 154.15 171.374 162.30 186.05 253.7 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 131.8 138.60 170.475 151.85 175.80 310.3 100
250 131.9 138.05 167.298 147.15 171.60 294.0 100
500 129.2 137.40 171.916 151.75 188.65 395.4 100
1000 125.0 136.60 168.648 148.65 170.40 303.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 1198.4 1285.00 1933.312 1543.75 2567.80 3129.0 100
250 1207.9 1271.95 1956.695 1996.65 2535.20 3965.8 100
500 1104.5 1194.30 1830.172 2105.70 2357.95 3134.9 100
1000 850.3 923.70 1384.385 1078.50 1860.65 2671.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 1188.1 1215.60 1248.079 1231.25 1257.95 1460.4 100
250 1178.0 1197.85 1243.659 1211.70 1241.55 1746.9 100
500 1077.9 1114.90 1154.485 1130.90 1169.30 1516.0 100
1000 802.3 861.20 907.983 878.90 916.30 1363.0 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 155.5 164.10 203.796 171.85 248.90 429.7 100
250 152.2 160.25 182.548 165.05 179.65 471.0 100
500 146.9 157.55 194.740 164.50 242.85 368.3 100
1000 140.5 145.50 171.645 149.90 173.50 390.8 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 158.4 166.1 193.426 173.95 199.55 349.8 100
250 154.1 165.2 196.453 173.90 211.35 324.8 100
500 154.4 161.4 194.788 173.65 205.85 379.4 100
1000 145.8 156.0 189.568 167.75 222.15 393.9 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 175.2 182.30 211.974 190.95 227.40 390.0 100
250 174.0 184.50 225.264 200.20 269.05 439.9 100
500 166.3 176.55 214.754 187.80 255.40 476.8 100
1000 158.4 168.35 210.854 181.75 259.10 358.9 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 962.7 1163.50 1327.955 1275.90 1363.60 7991.6 100
250 948.8 1139.70 1311.607 1206.20 1263.55 7980.4 100
500 907.4 1067.45 1261.210 1140.10 1215.50 7784.5 100
1000 787.0 919.10 997.542 1005.85 1070.05 1581.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 1125.5 1345.25 1546.605 1503.15 1611.10 6494.6 100
250 1109.2 1267.50 1502.428 1435.40 1560.05 5588.4 100
500 1045.0 1222.00 1389.189 1326.80 1426.20 6138.6 100
1000 881.3 1023.95 1181.655 1141.75 1231.15 6248.4 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 827.2 891.10 1032.909 974.75 1081.70 5266.4 100
250 824.1 883.95 1025.837 969.65 1067.65 5325.7 100
500 793.1 843.45 929.815 916.60 1008.60 1122.2 100
1000 737.9 781.05 982.718 810.00 949.45 5166.6 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 3078.4 4493.15 6160.442 5252.95 7823.05 11215.0 100
250 3120.8 4420.90 5979.924 5009.00 7948.65 11372.0 100
500 3040.2 4115.60 5756.970 4859.55 7704.40 10901.1 100
1000 2960.5 4267.30 5925.290 4835.95 7522.10 18233.1 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