Skip to content

Commit

Permalink
Added cor2cov and cov2cor methods. (JuliaLang#261)
Browse files Browse the repository at this point in the history
* Added `cor2cov` and `cov2cor` methods.

* Switched to accepting `AbstractMatrix` vs `DenseMatrix`.

* Added an in-place version of cor2cov and update the docs to mention the in-place versions.

* Added in-place specific tests.
  • Loading branch information
rofinn authored and ararslan committed May 18, 2017
1 parent 66b2b3e commit 2a2653e
Show file tree
Hide file tree
Showing 4 changed files with 114 additions and 0 deletions.
8 changes: 8 additions & 0 deletions docs/source/cov.rst
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,11 @@ This package implements functions for computing scatter matrix, as well as weigh
A weighting vector ``wv`` can be specified. ``vardim`` that designates whether the variables are columns in the matrix (``1``) or rows (``2``).
Finally, bias correction is applied to the covariance calculation if ``corrected=true``.
See ``cov`` documentation for more details.

.. function:: cov2cor(C, s)

Compute the correlation matrix from the covariance matrix ``C`` and a vector of standard deviations ``s``. Use ``Base.cov2cor!`` for an in-place version.

.. function:: cor2cov(C, s)

Compute the covariance matrix from the correlation matrix ``C`` and a vector of standard deviations ``s``. Use ``StatsBase.cor2cov!`` for an in-place version.
2 changes: 2 additions & 0 deletions src/StatsBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ module StatsBase

# cov
scattermat, # scatter matrix (i.e. unnormalized covariance)
cov2cor, # converts a covariance matrix to a correlation matrix
cor2cov, # converts a correlation matrix to a covariance matrix

## counts
addcounts!, # add counts to an accumulating array or map
Expand Down
31 changes: 31 additions & 0 deletions src/cov.jl
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,34 @@ function mean_and_cov(x::DenseMatrix, wv::AbstractWeights, vardim::Int=1;
m = mean(x, wv, vardim)
return m, Base.cov(x, wv, vardim; corrected=depcheck(:mean_and_cov, corrected))
end

"""
cov2cor(C, s)
Compute the correlation matrix from the covariance matrix `C` and a vector of standard
deviations `s`. Use `Base.cov2cor!` for an in-place version.
"""
cov2cor(C::AbstractMatrix, s::AbstractArray) = Base.cov2cor!(copy(C), s)

"""
cor2cov(C, s)
Compute the covariance matrix from the correlation matrix `C` and a vector of standard
deviations `s`. Use `StatsBase.cor2cov!` for an in-place version.
"""
cor2cov(C::AbstractMatrix, s::AbstractArray) = cor2cov!(copy(C), s)

"""
cor2cov!(C, s)
Converts the correlation matrix `C` to a covariance matrix in-place using a vector of
standard deviations `s`.
"""
function cor2cov!(C::AbstractMatrix, s::AbstractArray)
n = length(s)
size(C) == (n, n) || throw(DimensionMismatch("inconsistent dimensions"))
for i in CartesianRange(size(C))
@inbounds C[i] *= s[i[1]] * s[i[2]]
end
return C
end
73 changes: 73 additions & 0 deletions test/cov.jl
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,29 @@ weight_funcs = (weights, aweights, fweights, pweights)
@test m == mean(X, wv2, 2)
@test C == cov(X, wv2, 2; corrected=false)
end
@testset "Conversions" begin
std1 = std(X, wv1, 1; corrected=false)
std2 = std(X, wv2, 2; corrected=false)

cov1 = cov(X, wv1, 1; corrected=false)
cov2 = cov(X, wv2, 2; corrected=false)

cor1 = cor(X, wv1, 1)
cor2 = cor(X, wv2, 2)

@testset "cov2cor" begin
@test cov2cor(cov(X, 1), std(X, 1)) cor(X, 1)
@test cov2cor(cov(X, 2), std(X, 2)) cor(X, 2)
@test cov2cor(cov1, std1) cor1
@test cov2cor(cov2, std2) cor2
end
@testset "cor2cov" begin
@test cor2cov(cor(X, 1), std(X, 1)) cov(X, 1)
@test cor2cov(cor(X, 2), std(X, 2)) cov(X, 2)
@test cor2cov(cor1, std1) cov1
@test cor2cov(cor2, std2) cov2
end
end
end

@testset "Corrected" begin
Expand Down Expand Up @@ -153,6 +176,56 @@ weight_funcs = (weights, aweights, fweights, pweights)
@test C == cov(X, wv2, 2; corrected=true)
end
end
@testset "Conversions" begin
if !isa(wv1, Weights)
std1 = std(X, wv1, 1; corrected=true)
std2 = std(X, wv2, 2; corrected=true)

cov1 = cov(X, wv1, 1; corrected=true)
cov2 = cov(X, wv2, 2; corrected=true)

cor1 = cor(X, wv1, 1)
cor2 = cor(X, wv2, 2)

@testset "cov2cor" begin
@test cov2cor(cov(X, 1), std(X, 1)) cor(X, 1)
@test cov2cor(cov(X, 2), std(X, 2)) cor(X, 2)
@test cov2cor(cov1, std1) cor1
@test cov2cor(cov2, std2) cor2
end

@testset "cov2cor!" begin
tmp_cov1 = copy(cov1)
@test !(tmp_cov1 cor1)
Base.cov2cor!(tmp_cov1, std1)
@test tmp_cov1 cor1

tmp_cov2 = copy(cov2)
@test !(tmp_cov2 cor2)
Base.cov2cor!(tmp_cov2, std2)
@test tmp_cov2 cor2
end

@testset "cor2cov" begin
@test cor2cov(cor(X, 1), std(X, 1)) cov(X, 1)
@test cor2cov(cor(X, 2), std(X, 2)) cov(X, 2)
@test cor2cov(cor1, std1) cov1
@test cor2cov(cor2, std2) cov2
end

@testset "cor2cov!" begin
tmp_cor1 = copy(cor1)
@test !(tmp_cor1 cov1)
StatsBase.cor2cov!(tmp_cor1, std1)
@test tmp_cor1 cov1

tmp_cor2 = copy(cor2)
@test !(tmp_cor2 cov2)
StatsBase.cor2cov!(tmp_cor2, std2)
@test tmp_cor2 cov2
end
end
end
end

@testset "Correlation" begin
Expand Down

0 comments on commit 2a2653e

Please sign in to comment.