|
11 | 11 | % reduce Monte Carlo error [2,3]. |
12 | 12 | % |
13 | 13 | % If single bootstrap is requested, the confidence intervals are obtained from |
14 | | -% the quantiles of a kernel density estimate of bootstrap statistics (with |
| 14 | +% the quantiles of a kernel density estimate of the bootstrap statistics (with |
15 | 15 | % shrinkage corrrection). By default, the confidence intervals are bias- |
16 | 16 | % corrected and accelerated (BCa) [4-5]. BCa intervals are fast to compute and |
17 | 17 | % have good coverage and correctness when combined with bootknife resampling |
|
20 | 20 | % If double bootstrap is requested, the algorithm uses calibration to improve |
21 | 21 | % the accuracy (of the bias and standard error) and coverage of the confidence |
22 | 22 | % intervals [6-12], which are obtained from the empirical distribution of the |
23 | | -% bootstrap statistics by linear interpolation. |
| 23 | +% bootstrap statistics by linear interpolation [9]. |
24 | 24 | % |
25 | 25 | % STATS = bootknife (DATA) |
26 | 26 | % STATS = bootknife ({DATA}) |
|
30 | 30 | % STATS = bootknife (DATA, NBOOT, ..., ALPHA) |
31 | 31 | % STATS = bootknife (DATA, NBOOT, ..., ALPHA, STRATA) |
32 | 32 | % STATS = bootknife (DATA, NBOOT, ..., ALPHA, STRATA, NPROC) |
| 33 | +% STATS = bootknife (DATA, NBOOT, ..., ALPHA, STRATA, NPROC, BOOTSAM) |
33 | 34 | % [STATS, BOOTSTAT] = bootknife (...) |
34 | 35 | % [STATS, BOOTSTAT] = bootknife (...) |
35 | 36 | % [STATS, BOOTSTAT, BOOTSAM] = bootknife (...) |
|
155 | 156 | % feature requires the Parallel package (in Octave), or the Parallel |
156 | 157 | % Computing Toolbox (in Matlab). |
157 | 158 | % |
| 159 | +% STATS = bootknife (DATA, NBOOT, ..., ALPHA, STRATA, NPROC, BOOTSAM) uses |
| 160 | +% bootstrap resampling indices provided in BOOTSAM. The BOOTSAM should be a |
| 161 | +% matrix with the same number of rows as the data. When BOOTSAM is provided, |
| 162 | +% the first element of NBOOT is ignored. |
| 163 | +% |
158 | 164 | % [STATS, BOOTSTAT] = bootknife (...) also returns BOOTSTAT, a vector of |
159 | 165 | % bootstrap statistics calculated over the (first, or outer layer of) |
160 | 166 | % bootstrap resamples. |
|
187 | 193 | % Bootstrap. New York, NY: Chapman & Hall |
188 | 194 | % [6] Beran (1987). Prepivoting to Reduce Level Error of Confidence Sets. |
189 | 195 | % Biometrika, 74(3), 457–468. |
190 | | -% [7] Lee and Young (1999) The effectt of Monte Carlo approximation on coverage |
| 196 | +% [7] Lee and Young (1999) The effect of Monte Carlo approximation on coverage |
191 | 197 | % error of double-bootstrap con®dence intervals. J R Statist Soc B. |
192 | 198 | % 61:353-366. |
193 | 199 | % [8] Booth J. and Presnell B. (1998) Allocation of Monte Carlo Resources for |
|
225 | 231 | % along with this program. If not, see <http://www.gnu.org/licenses/>. |
226 | 232 |
|
227 | 233 |
|
228 | | -function [stats, bootstat, BOOTSAM] = bootknife (x, nboot, bootfun, alpha, ... |
229 | | - strata, ncpus, REF, ISOCTAVE, BOOTSAM, ERRCHK) |
| 234 | +function [stats, bootstat, bootsam] = bootknife (x, nboot, bootfun, alpha, ... |
| 235 | + strata, ncpus, bootsam, REF, ISOCTAVE, ERRCHK) |
230 | 236 |
|
231 | 237 | % Input argument names in all-caps are for internal use only |
232 | | - % REF, ISOCTAVE, BOOTSAM, ERRCHK are undocumented input arguments required |
| 238 | + % REF, ISOCTAVE and ERRCHK are undocumented input arguments required |
233 | 239 | % for some of the functionalities of bootknife |
234 | 240 |
|
235 | 241 | % Store local functions in a stucture for parallel processes |
|
343 | 349 | error ('bootknife: NPROC must be a scalar value'); |
344 | 350 | end |
345 | 351 | end |
346 | | - if ((nargin < 8) || isempty (ISOCTAVE)) |
| 352 | + if ((nargin < 9) || isempty (ISOCTAVE)) |
347 | 353 | % Check if running in Octave (else assume Matlab) |
348 | 354 | info = ver; |
349 | 355 | ISOCTAVE = any (ismember ({info.Name}, 'Octave')); |
|
511 | 517 |
|
512 | 518 | % Perform balanced bootknife resampling |
513 | 519 | unbiased = true; % Set to true for bootknife resampling |
514 | | - if ((nargin < 9) || isempty (BOOTSAM)) |
| 520 | + if ((nargin < 7) || isempty (bootsam)) |
515 | 521 | if (~ isempty (strata)) |
516 | 522 | if (nvar > 1) || (nargout > 2) |
517 | | - % We can save some memory by making BOOTSAM an int32 datatype |
518 | | - BOOTSAM = zeros (n, B, 'int32'); |
| 523 | + % We can save some memory by making bootsam an int32 datatype |
| 524 | + bootsam = zeros (n, B, 'int32'); |
519 | 525 | for k = 1:K |
520 | 526 | if ((sum (g(:, k))) > 1) |
521 | | - BOOTSAM(g(:, k), :) = boot (find (g(:, k)), B, unbiased); |
| 527 | + bootsam(g(:, k), :) = boot (find (g(:, k)), B, unbiased); |
522 | 528 | else |
523 | | - BOOTSAM(g(:, k), :) = find (g(:, k)) * ones (1, B); |
| 529 | + bootsam(g(:, k), :) = find (g(:, k)) * ones (1, B); |
524 | 530 | end |
525 | 531 | end |
526 | 532 | else |
527 | | - % For more efficiency, if we don't need BOOTSAM, we can directly resample values of x |
528 | | - BOOTSAM = []; |
| 533 | + % For more efficiency, if we don't need bootsam, we can directly resample values of x |
| 534 | + bootsam = []; |
529 | 535 | X = zeros (n, B); |
530 | 536 | for k = 1:K |
531 | 537 | if ((sum (g(:, k))) > 1) |
|
537 | 543 | end |
538 | 544 | else |
539 | 545 | if (nvar > 1) || (nargout > 2) |
540 | | - % We can save some memory by making BOOTSAM an int32 datatype |
541 | | - BOOTSAM = zeros (n, B, 'int32'); |
542 | | - BOOTSAM(:, :) = boot (n, B, unbiased); |
| 546 | + % We can save some memory by making bootsam an int32 datatype |
| 547 | + bootsam = zeros (n, B, 'int32'); |
| 548 | + bootsam(:, :) = boot (n, B, unbiased); |
543 | 549 | else |
544 | | - % For more efficiency, if we don't need BOOTSAM, we can directly resample values of x |
545 | | - BOOTSAM = []; |
| 550 | + % For more efficiency, if we don't need bootsam, we can directly resample values of x |
| 551 | + bootsam = []; |
546 | 552 | X = boot (x, B, unbiased); |
547 | 553 | end |
548 | 554 | end |
| 555 | + else |
| 556 | + if (size (bootsam, 1) ~= n) |
| 557 | + error ('bootknife: BOOTSAM must have the same number of rows as X') |
| 558 | + end |
| 559 | + nboot(1) = size (bootsam, 2); |
| 560 | + B = nboot(1); |
549 | 561 | end |
550 | 562 |
|
551 | 563 | % Evaluate bootfun each bootstrap resample |
552 | | - if (isempty (BOOTSAM)) |
| 564 | + if (isempty (bootsam)) |
553 | 565 | if (vectorized) |
554 | 566 | % Vectorized evaluation of bootfun on the DATA resamples |
555 | 567 | bootstat = bootfun (X); |
|
570 | 582 | end |
571 | 583 | else |
572 | 584 | if (vectorized) |
573 | | - % DATA resampling (using BOOTSAM) and vectorized evaluation of bootfun on |
| 585 | + % DATA resampling (using bootsam) and vectorized evaluation of bootfun on |
574 | 586 | % the DATA resamples |
575 | 587 | if (nvar > 1) |
576 | 588 | % Multivariate |
577 | 589 | % Perform DATA sampling |
578 | | - X = cell2mat (cellfun (@(i) reshape (x(BOOTSAM, i), n, B), ... |
| 590 | + X = cell2mat (cellfun (@(i) reshape (x(bootsam, i), n, B), ... |
579 | 591 | num2cell (1:nvar, 1), 'UniformOutput', false)); |
580 | 592 | else |
581 | 593 | % Univariate |
582 | 594 | % Perform DATA sampling |
583 | | - X = x(BOOTSAM); |
| 595 | + X = x(bootsam); |
584 | 596 | end |
585 | 597 | % Function evaluation on bootknife samples |
586 | 598 | bootstat = bootfun (X); |
587 | 599 | else |
588 | | - cellfunc = @(BOOTSAM) bootfun (x(BOOTSAM, :)); |
| 600 | + cellfunc = @(bootsam) bootfun (x(bootsam, :)); |
589 | 601 | if (ncpus > 1) |
590 | 602 | % Evaluate bootfun on each bootstrap resample in PARALLEL |
591 | 603 | if (ISOCTAVE) |
592 | 604 | % OCTAVE |
593 | | - bootstat = parcellfun (ncpus, cellfunc, num2cell (BOOTSAM, 1), 'UniformOutput', false); |
| 605 | + bootstat = parcellfun (ncpus, cellfunc, num2cell (bootsam, 1), 'UniformOutput', false); |
594 | 606 | else |
595 | 607 | % MATLAB |
596 | 608 | bootstat = cell (1, B); |
597 | | - parfor b = 1:B; bootstat{b} = cellfunc (BOOTSAM(:, b)); end |
| 609 | + parfor b = 1:B; bootstat{b} = cellfunc (bootsam(:, b)); end |
598 | 610 | end |
599 | 611 | else |
600 | 612 | % Evaluate bootfun on each bootstrap resample in SERIAL |
601 | | - bootstat = cellfun (cellfunc, num2cell (BOOTSAM, 1), 'UniformOutput', false); |
| 613 | + bootstat = cellfun (cellfunc, num2cell (bootsam, 1), 'UniformOutput', false); |
602 | 614 | end |
603 | 615 | end |
604 | 616 | end |
|
607 | 619 | end |
608 | 620 |
|
609 | 621 | % Remove bootstrap statistics that contain NaN, along with their associated |
610 | | - % DATA resamples in X or BOOTSAM |
| 622 | + % DATA resamples in X or bootsam |
611 | 623 | ridx = any (isnan (bootstat), 1); |
612 | 624 | bootstat_all = bootstat; |
613 | 625 | bootstat(:, ridx) = []; |
614 | | - if (isempty (BOOTSAM)) |
| 626 | + if (isempty (bootsam)) |
615 | 627 | X(:, ridx) = []; |
616 | 628 | else |
617 | | - BOOTSAM(:, ridx) = []; |
| 629 | + bootsam(:, ridx) = []; |
618 | 630 | end |
619 | 631 | if (isempty (bootstat)) |
620 | 632 | error ('bootknife: BOOTFUN returned NaN for every bootstrap resamples') |
|
630 | 642 | % OCTAVE |
631 | 643 | % Set unique random seed for each parallel thread |
632 | 644 | pararrayfun (ncpus, @boot, 1, 1, false, 1:ncpus); |
633 | | - if (vectorized && isempty (BOOTSAM)) |
634 | | - cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
| 645 | + if (vectorized && isempty (bootsam)) |
| 646 | + cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
635 | 647 | bootout = parcellfun (ncpus, cellfunc, num2cell (X, 1), 'UniformOutput', false); |
636 | 648 | else |
637 | | - cellfunc = @(BOOTSAM) bootknife (x(BOOTSAM, :), C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
638 | | - bootout = parcellfun (ncpus, cellfunc, num2cell (BOOTSAM, 1), 'UniformOutput', false); |
| 649 | + cellfunc = @(bootsam) bootknife (x(bootsam, :), C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
| 650 | + bootout = parcellfun (ncpus, cellfunc, num2cell (bootsam, 1), 'UniformOutput', false); |
639 | 651 | end |
640 | 652 | else |
641 | 653 | % MATLAB |
|
644 | 656 | % Perform inner layer of resampling |
645 | 657 | % Preallocate structure array |
646 | 658 | bootout = cell (1, B); |
647 | | - if (vectorized && isempty (BOOTSAM)) |
648 | | - cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
| 659 | + if (vectorized && isempty (bootsam)) |
| 660 | + cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
649 | 661 | parfor b = 1:B; bootout{b} = cellfunc (X(:, b)); end |
650 | 662 | else |
651 | | - cellfunc = @(BOOTSAM) bootknife (x(BOOTSAM, :), C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
652 | | - parfor b = 1:B; bootout{b} = cellfunc (BOOTSAM(:, b)); end |
| 663 | + cellfunc = @(bootsam) bootknife (x(bootsam, :), C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
| 664 | + parfor b = 1:B; bootout{b} = cellfunc (bootsam(:, b)); end |
653 | 665 | end |
654 | 666 | end |
655 | 667 | else |
656 | 668 | % SERIAL execution of inner layer resampling for double bootstrap |
657 | | - if (vectorized && isempty (BOOTSAM)) |
658 | | - cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
| 669 | + if (vectorized && isempty (bootsam)) |
| 670 | + cellfunc = @(x) bootknife (x, C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
659 | 671 | bootout = cellfun (cellfunc, num2cell (X, 1), 'UniformOutput', false); |
660 | 672 | else |
661 | | - cellfunc = @(BOOTSAM) bootknife (x(BOOTSAM, :), C, bootfun, NaN, strata, 0, T0, ISOCTAVE, [], false); |
662 | | - bootout = cellfun (cellfunc, num2cell (BOOTSAM, 1), 'UniformOutput', false); |
| 673 | + cellfunc = @(bootsam) bootknife (x(bootsam, :), C, bootfun, NaN, strata, 0, [], T0, ISOCTAVE, false); |
| 674 | + bootout = cellfun (cellfunc, num2cell (bootsam, 1), 'UniformOutput', false); |
663 | 675 | end |
664 | 676 | end |
665 | 677 | % Double bootstrap bias estimation |
|
807 | 819 | stats.CI_lower = ci(:, 1); |
808 | 820 | stats.CI_upper = ci(:, 2); |
809 | 821 | % Use quick interpolation to find the proportion (Pr) of bootstat <= REF |
810 | | - if ((nargin > 6) && ~ isempty (REF)) |
| 822 | + if ((nargin > 7) && ~ isempty (REF)) |
811 | 823 | I = bsxfun (@le, bootstat, REF); |
812 | 824 | pr = sum (I, 2); |
813 | 825 | t = cell2mat (arrayfun (@(j) ... |
|
828 | 840 | if (nargout == 0) |
829 | 841 | print_output (stats, nboot, alpha, l, m, bootfun_str, strata); |
830 | 842 | else |
831 | | - if (isempty (BOOTSAM)) |
| 843 | + if (isempty (bootsam)) |
832 | 844 | [warnmsg, warnID] = lastwarn; |
833 | 845 | if (ismember (warnID, {'bootknife:biasfail','bootknife:jackfail'})) |
834 | 846 | warning ('bootknife:lastwarn', warnmsg); |
|
0 commit comments