Package: ccc-coef
Clustermatch Correlation Coefficient (CCC)OverviewThe Clustermatch Correlation Coefficient (CCC) is a highly-efficient, next-generation not-only-linear correlation coefficient that can work on numerical and categorical data types.
This repository contains the code of CCC and instructions to install and use it.
It also has all the scripts/notebooks to run the analyses associated with themanuscript, where we applied CCC on gene expression data.InstallationCCC is available as a PyPI (Python) package (ccc-coef). We tested CCC in Python 3.9+, but it should work on prior 3.x versions.
You can quickly test it by creating a conda environment and then install it withpip:# ipython and pandas are used in the following examples, but they are not needed for CCC to workcondacreate-y-nccc-envpython=3.9ipythonpandas
condaactivateccc-env
pipinstallccc-coefUsageRunipythonin your terminal:$ipython
Python3.10.4(main,Mar312022,08:41:55)[GCC7.5.0]Type'copyright','credits'or'license'formoreinformation
IPython8.3.0--AnenhancedInteractivePython.Type'?'forhelp.

In[1]:When computing the correlation coefficient on a pair of features, CCC supportsnumpy.arrayorpandas.Series.
Missing values (NaN) are not currently supported, so you have to either remove or impute them.
Below there is an example with numerical data (you can copy/paste the entire lines below includingIn [...]):In[1]:importnumpyasnpIn[2]:importpandasaspdIn[3]:fromccc.coefimportcccIn[4]:random_feature1=np.random.rand(1000)In[5]:random_feature2=np.random.rand(1000)In[6]:ccc(random_feature1,random_feature2)Out[6]:0.0018815884476534295In[7]:random_feature1=pd.Series(random_feature1)In[8]:random_feature2=pd.Series(random_feature2)In[9]:ccc(random_feature1,random_feature2)Out[9]:0.0018815884476534295CCC always returns a value between zero (no relationship) and one (perfect relationship).As we show in the manuscript, the distribution of CCC values is much more skewed than other coefficients like Pearson's or Spearman's.
A comparison between these coefficients should account for that.You can also mix numerical and categorical data:In[10]:categories=np.array(["blue","red","green","yellow"])In[11]:categorical_random_feature1=np.random.choice(categories,size=1000)In[12]:categorical_random_feature2=np.random.choice(categories,size=1000)In[13]:categorical_random_feature2[:10]Out[13]:array(['yellow','red','red','yellow','blue','blue','red','yellow','green','blue'],dtype='<U6')In[14]:ccc(categorical_random_feature1,categorical_random_feature2)Out[14]:0.0009263483455638076In[15]:ccc(random_feature1,categorical_random_feature2)Out[15]:0.0015123522641692117The first argument ofccccould also be a matrix, either as anumpy.array(features are in rows and objects in columns) or as apandas.DataFrame(objects are in rows and features in columns).
In this case,cccwill compute the pairwise correlation across all features:In[16]:# with a numpy.arrayIn[17]:data=np.random.rand(10,1000)In[18]:c=ccc(data)In[19]:c.shapeOut[19]:(45,)In[20]:c[:10]Out[20]:array([0.00404461,0.00185342,0.00248847,0.00232761,0.00260786,0.00121495,0.00227679,0.00099051,0.00313611,0.00323936])In[21]:# with a pandas.DataFrameIn[22]:data_df=pd.DataFrame(data.T)In[23]:c=ccc(data_df)In[24]:c.shapeOut[24]:(45,)In[25]:c[:10]Out[25]:array([0.00404461,0.00185342,0.00248847,0.00232761,0.00260786,0.00121495,0.00227679,0.00099051,0.00313611,0.00323936])If your data has a mix of numerical and categorical features, it's better to work on apandas.DataFrame.
As an example, we load theTitanic dataset(fromseaborn's repository):In[26]:titanic_url="https://raw.githubusercontent.com/mwaskom/seaborn-data/master/raw/titanic.csv"In[27]:titanic_df=pd.read_csv(titanic_url)In[28]:titanic_df.shapeOut[28]:(891,11)In[29]:titanic_df.head()Out[29]:survivedpclassnamesexagesibspparchticketfarecabinembarked003Braund,Mr.OwenHarrismale22.010A/5211717.2500NaNS111Cumings,Mrs.JohnBradley(FlorenceBriggsTh...female38.010PC1759971.2833C85C213Heikkinen,Miss.Lainafemale26.000STON/O2.31012827.9250NaNS311Futrelle,Mrs.JacquesHeath(LilyMayPeel)female35.01011380353.1000C123S403Allen,Mr.WilliamHenrymale35.0003734508.0500NaNSThe Titanic dataset has missing values:In[30]:titanic_df.isna().sum()Out[30]:survived0pclass0name0sex0age177sibsp0parch0ticket0fare0cabin687embarked2dtype:int64So we need some kind of preprocessing before moving on:In[31]:titanic_df=titanic_df.dropna(subset=["embarked"]).dropna(axis=1)In[32]:titanic_df.shapeOut[32]:(889,9)Now we can run CCC on the dataset and get a correlation matrix across features:In[33]:ccc_corrs=ccc(titanic_df)In[34]:fromscipy.spatial.distanceimportsquareformIn[35]:ccc_corrs=squareform(ccc_corrs)In[36]:np.fill_diagonal(ccc_corrs,1.0)In[37]:ccc_corrs=pd.DataFrame(ccc_corrs,index=titanic_df.columns.tolist(),columns=titanic_df.columns.tolist())In[38]:ccc_corrs.shapeOut[38]:(9,9)In[39]:withpd.option_context('display.float_format','{:,.2f}'.format):display(ccc_corrs)survivedpclassnamesexsibspparchticketfareembarkedsurvived1.000.120.000.320.040.050.000.070.05pclass0.121.000.000.040.020.010.000.330.01name0.000.001.000.000.000.000.000.000.00sex0.320.040.001.000.080.110.000.040.04sibsp0.040.020.000.081.000.290.000.230.00parch0.050.010.000.110.291.000.000.140.00ticket0.000.000.000.000.000.001.000.020.00fare0.070.330.000.040.230.140.021.000.03embarked0.050.010.000.040.000.000.000.031.00Thecccfunction also has an_jobsparameter that allows to control the number of CPU cores used.
Parallelization worksacrossvariable pairs (if a matrix/dataframe is provided) or by internally distributing computation of a single variable pair.In the first example below, we compute the pairwise correlation between 20 features across 1000 objects:In[40]:data=np.random.rand(20,1000)In[41]:%timeitccc(data,n_jobs=1)1.32s±45.8msperloop(mean±std.dev.of7runs,1loopeach)In[42]:%timeitccc(data,n_jobs=2)771ms±11msperloop(mean±std.dev.of7runs,1loopeach)And here we parallelize the computation of a single variable pair with thousands of objects:In[43]:x=np.random.normal(size=100000)In[44]:y=np.random.normal(size=100000)In[45]:%timeitccc(x,y,n_jobs=1)956ms±3.47msperloop(mean±std.dev.of7runs,1loopeach)In[46]:%timeitccc(x,y,n_jobs=2)559ms±5.82msperloop(mean±std.dev.of7runs,1loopeach)Reproducible researchBelow we provide the steps to reproduce all the analyses in the CCC manuscript.
All the analyses are written as Jupyter notebooks and stored in the foldernbs/.
All notebooks are organized by directories, such as01_preprocessing, with file names that indicate the order in which they should be run.Here you have the option to createaminimal environmentto run analyses within your browser, orafull environmentready to run all the analyses in your browser or from the command-line (this might be helpful if you plan to launch long-running jobs).Setup of a minimal environmentTo set up a minimal environment, you first need toinstall Dockerfor your system.
Then, open a terminal and run this code:# pulls/downloads the Docker image with the environment and source codesudodockerpullmiltondp/ccc# specify a base directory to store data and codeexportBASE_FOLDER="/tmp/ccc"mkdir-p${BASE_FOLDER}# specify a directory in your computer where data and results will be storedexportDATA_FOLDER="${BASE_FOLDER}/data"mkdir-p${DATA_FOLDER}# specify a directory where the source code isexportCODE_FOLDER="${BASE_FOLDER}/code"gitclonehttps://github.com/greenelab/ccc.git${CODE_FOLDER}# download the necessary data (GTEx, etc)dockerrun--rm\-v"${DATA_FOLDER}:/opt/data"\-v"${CODE_FOLDER}:/opt/code"\--user"$(id-u):$(id-g)"\miltondp/ccc\/bin/bash-c"python environment/scripts/setup_data.py"# run JupyterLab serverdockerrun--rm\-p8893:8893\-v"${DATA_FOLDER}:/opt/data"\-v"${CODE_FOLDER}:/opt/code"\--user"$(id-u):$(id-g)"\miltondp/cccThen open your browser and navigate tohttp://127.0.0.1:8893/.
With the Jupyter interface, you should open the foldernbs/, and then open and run the notebooks in order.
For example, you must start with all notebooks in05_preprocessingfirst (run them in order too), then10_compute_correlations, etc.
All data and results will be saved in folderDATA_FOLDER, and the code that you change will be saved in your computer under folderCODE_FOLDER.
And that's it, you should be able to run all the analyses within your browser.Setup of a full environmentTo set up a full environment, please follow the steps inenvironment.
After completing those steps, you'll have the source code in this repository, a Python environment (either using a Docker image or creating your own conda environment) and the necessary data to run the analyses.Once the full environment is set up, then you have two options to run the analyses/notebooks:Using the browser:Start the JupyterLab server.Use your browser to open and run the notebooks.Using the command-line:Open a terminal.Run the notebooks from usingpapermill.Using the browser.This option is the standard one and it is likely the one you want to use.
You can run each cell in the notebook, see the output, and change the code if you want.
For example, let's say you want to run the data preprocessing notebooks.
First, you need to start the JupyterLab server.
For this, you can run one of the commands below depending on whether you are using your own conda environment or Docker:# if you're using your own conda environmentbashscripts/run_nbs_server.sh# if you're using Docker# this will internally run 'bash scripts/run_nbs_server.sh'bashscripts/run_docker.shand then go tohttp://127.0.0.1:8893/and browse tonbs/05_preprocessing.
Then you need to run each notebook in order.Using the command-line.This is an alternative approach to run notebooks in a more systematic way.
You'll likely not use this option unless you want to run your own analyses in a cluster, for instance.
Here we use the terminal and a tool calledpapermillto run each notebook and write back the results (like figures, etc).
You can see some output in the terminal when it's running, and once finished, you can start the JupyterLab server and open the notebook to see the results.Using as example the same preprocessing notebooks, you can run all the preprocessing notebooks in order:# if you're using your own conda environment#   requires GNU Parallel: https://www.gnu.org/software/parallel/#   To install in Ubuntu: apt install parallelparallel\-k\--lb\--halt2\-j1\'bash nbs/run_nbs.sh {}':::nbs/05_preprocessing/*.ipynb# if you're using Docker#   GNU Parallel is already included in the Docker image,#   so no need to installbashscripts/run_docker.sh\parallel\-k\--lb\--halt2\-j1\'bash nbs/run_nbs.sh {}':::nbs/05_preprocessing/*.ipynbAny command that you add afterscripts/run_docker.shwill be run inside the Docker container.