Search code examples
rmatrixdistributionsampling

Sampling from Wishart distribution with p-1 < df < p in R


I need to sample a matrix from a Wishart distribution with degrees of freedom smaller than the dimensionality of the scale matrix. I'm struggling to find an R function that allows it.

For a Wishart distribution, the degrees of freedom (call them df or v) must be greater than the dimensionality of the scale matrix (say p) minus 1 (i.e. df > p - 1) (see https://en.wikipedia.org/wiki/Wishart_distribution or any manual on the Wishart distribution). However, when I try to sample from a wishart distribution with p-1 < df < p, say W(df = 1.1, I_p), where I_p is a pxp identity matrix, I get errors stating inconsistency of the degrees of freedom.

Say that p = 2, I want to sample from different Wishart distributions with df between 1 and 2 (excluded) but

stats::rWishart(n = 1, df = 1.1, Sigma = diag(2)) # does not work
MCMCpack::rwish(v = 1.1, S = diag(2)) # does not work

do not work.

I thought the problem might have been the non-integer degrees of freedom, but

stats::rWishart(n = 1, df = 2.1, Sigma = diag(2))
MCMCpack::rwish(v = 2.1, S = diag(2))

work without any problem.

I did find

  rWishart::rWishart(1, df = 1.1, Sigma = diag(2)) # works

which works, but then it doesn't if 1.5 =< df < 2

  rWishart::rWishart(1, df = 1.5, Sigma = diag(2)) # does not works

I would like to find way in R to sample from a Wishart distribution which has any degrees of freedom bigger than p-1 but smaller than p (p-1 < df < p). And it doesn't strictly matter to me whether the sampled matrix is singular or not.


Solution

  • As far as I know, matrixsampling is the only package offering this possibility (I am its author).

    library(matrixsampling)
    rwishart(3, nu = 1.1, Sigma = diag(2))
    # , , 1
    # 
    #            [,1]      [,2]
    # [1,]  0.7679333 -1.051319
    # [2,] -1.0513191  1.439281
    # 
    # , , 2
    # 
    #            [,1]       [,2]
    # [1,]  1.8536154 -0.9059983
    # [2,] -0.9059983  0.4449708
    # 
    # , , 3
    # 
    #           [,1]      [,2]
    # [1,] 0.9309460 0.6026472
    # [2,] 0.6026472 0.3901232
    

    If you really want to sample with the identity matrix as the scale matrix Sigma, you can do:

    matrixsampling:::rwishart_I(3, nu = 1.1, p = 2)
    

    (to be honnest, I don't remember what I've done, but this should be more efficient).