Learn R Programming

psych (version 2.4.6.26)

bigCor: Find large correlation matrices by stitching together smaller ones found more rapidly

Description

When analyzing many subjects (ie. 100,000 or more) with many variables (i.e. 1000 or more) core R can take a long time and sometime exceed memory limits (i.e. with 600K subjects and 6K variables). bigCor runs (in parallel if multicores are available) by breaking the variables into subsets (of size=size), finding all subset correlations, and then stitches the resulting matrices into one large matrix. Noticeable improvements in speed compared to cor.

Usage

bigCor(x, size = NULL, use = "pairwise",cor="pearson",correct=.5)

Value

The correlation matrix

Arguments

x

A data set of numeric variables

size

What should the size of the subsets be? Defaults to NCOL (x)/20

use

The standard correlation option. "pairwise" allows for missing data

cor

Defaults to Pearson correlations, alteratives are polychoric and spearman

correct

Correction for continuity for polychoric correlations. (see polychoric)

Author

William Revelle

Details

The data are divided into subsets of size=size. Correlations are then found for each subset and pairs of subsets.

Time is roughly linear with the number of cases and increases by the square of the number of variables. The benefit of more cores is noticeable. It seems as if with 4 cores, we should use sizes to split it into 8 or 12 sets. Otherwise we don't actually use all cores efficiently.

There is some overhead in using multicores. So for smaller problems (e.g. the 4,000 cases of the 145 items of the psychTools::spi data set, the timings are roughly .14 seconds for bigCor (default size) and .10 for normal cor. For small problems, this actually gets worse as we use more cores. The cross over point seems to be at roughly 5K subjects. (updated these timings to recognize the M1 Max chip. An increase of 4x in speed! They had been .44 and .36.)

The basic loop loops over the subsets. When the size is a integer subset of the number of variables and is a multiple of the number of cores, the multiple cores will be used more. Notice the benefit of 660/80 versus 660/100. But this breaks down if we try 660/165. Further notice the benefit when using a smaller subset (55) which led to the 4 cores being used more.

The following timings are included to help users tinker with parameters:

Timings (in seconds) for various problems with 645K subjects on an 8 core Mac Book Pro with a 2.4 GHZ Intell core i9.

options(mc.cores=4) (Because we have 8 we can work at the same time as we test this.)

First test it with 644,495 subjects and 1/10 of the number of possible variables. Then test it for somewhat fewer variables.

Variablessize2 cores4 corescompared to normal cor function
660100430434430
66080600348notice the improvement with 8ths
660165666(Stitching seems to have been very slow)
66055303Even better if we break it into 12ths!
500100332
322 secs480120408
365315 Better to change the size48060358

We also test it with fewer subjects. Time is roughly linear with number of subjects.

Variablessize2 cores4 corescompared to normal cor function Further comparisons with fewer subjects (100K)
480605731
47 with normal cor. Note the effect of n subjects!2005019.913.6
27.13100254.63.5

One last comparison, 10,000 subjects, showing the effect of getting the proper size value. You can tune on these smaller sets of subjects before trying large problems.

Variablessize2 cores4 corescompared to normal cor function
4801205.25.14.51
480602.92.884.51
480302.652.691480
202.732.77480
102.822.97too many splits?200
502.181.392.47 for normal cor (1.44 with 8 cores 2.99 with 1 core)200
251.21.172.47 for normal cor(1.16 with 8 cores, 1.17 with 1 core)
10025.64.52.56

Timings updated in 2/23 using a MacBook Pro with M1 max chip 10,000 subjects 953 variables suggests that a very small size (e.g. 20) is probably optimal

Variablessize2 cores4 cores8 corescompared to normal cor function953
207.924.552.8811.0495330
7.984.883.1511.04953408.22
5.143.6311.16953608.515.59
3.9311.16953808.315.594.14
11.169531208.336.224.7511.16

References

Examples of large data sets with massively missing data are taken from the SAPA project. e.g.,

William Revelle, Elizabeth M. Dworak, and David M. Condon (2021) Exploring the persome: The power of the item in understanding personality structure. Personality and Individual Differences, 169, tools:::Rd_expr_doi("10.1016/j.paid.2020.109905")

David Condon (2018)The SAPA Personality Inventory: an empirically-derived, hierarchically-organized self-report personality assessment model. PsyArXiv /sc4p9/ tools:::Rd_expr_doi("10.31234/osf.io/sc4p9")

See Also

pairwiseCountBig which will do the same, but find the count of observations per cell.

Examples

Run this code
R <- bigCor(bfi,10)
#compare the results with 
r.bfi <- cor(bfi,use="pairwise")
all.equal(R,r.bfi)

Run the code above in your browser using DataLab