Function Repository Resource:

ConditionedMultinormalDistribution

Source Notebook

Calculate conditional and marginal distributions of the multivariate normal distribution

Contributed by: Sjoerd Smit

ResourceFunction["ConditionedMultinormalDistribution"][MultinormalDistribution[μ,Σ],ixi]

returns the MultinormalDistribution obtained by conditioning coordinate i to value xi.

ResourceFunction["ConditionedMultinormalDistribution"][,{i1xi1,i2xi2,}]

conditions on multiple coordinates.

ResourceFunction["ConditionedMultinormalDistribution"][,{i1,i2,}{xi1,xi2,}]

can also be used.

ResourceFunction["ConditionedMultinormalDistribution"][,,{n1,n2,}]

returns the marginal distributions of coordinates ni after conditioning.

ResourceFunction["ConditionedMultinormalDistribution"][Inactive[MultinormalDistribution][],]

works with SparseArray and SymmetrizedArray objects.

Details and Options

ResourceFunction["ConditionedMultinormalDistribution"] attempts to fill a gap in the functionality of Conditioned, which currently only works with functions like Probability and Expectation but cannot be used to transform distributions. In particular, Conditioned does not work with TransformedDistribution. Conditioning of distributions is generally non-trivial, but for the MultinormalDistribution, there exist exact analytical formulas.
ResourceFunction["ConditionedMultinormalDistribution"] works with TransformedDistribution. Conditioning of distributions is generally non-trivial, but for the MultinormalDistribution, there exist exact analytical formulas.
As an example, if we have a triple of numbers with joint distribution Distributed[{x1,x2,x3},MultinormalDistribution[μ,Σ]], then ResourceFunction["ConditionedMultinormalDistribution"][MultinormalDistribution[μ,Σ],30] is the distribution of the pair {x1,x2} given the knowledge that x3 is equal to 0 (i.e. the distribution ).
Calculating the conditioned distribution involves matrix inversion, so for distributions with many coordinates, it is recommended to only request the marginals of interest since computing the full distribution can be expensive.
Like MarginalDistribution, ResourceFunction["ConditionedMultinormalDistribution"][,,{n1,n2,}] will permute the indices of the resulting distribution according the specification {n1,n2,}. For example, the specification {2,1} will swap dimensions 1 and 2.
The specification All can also be used for the marginals.
ResourceFunction["ConditionedMultinormalDistribution"][,,n] returns a NormalDistribution while ResourceFunction["ConditionedMultinormalDistribution"][,,{n}] returns a one-dimensional MultinormalDistribution.
When using Inactive[MultinormalDistribution][], the covariance matrix will not be tested for being positive definite.

Examples

Basic Examples (3) 

Condition a 2D symbolic multivariate normal distribution on the value of the second coordinate:

In[1]:=
dist = MultinormalDistribution[{\[Mu]1, \[Mu]2}, {{\[CapitalSigma]11, \[CapitalSigma]12}, {\[CapitalSigma]12, \[CapitalSigma]22}}];
ResourceFunction["ConditionedMultinormalDistribution"][dist, 2 -> x2]
Out[2]=

A NormalDistribution is returned if you specify that the first marginal should be computed:

In[3]:=
ResourceFunction["ConditionedMultinormalDistribution"][dist, 2 -> x2,
  1]
Out[3]=

Generate a random MultinormalDistribution:

In[4]:=
randomDist = With[{dim = 10},
   MultinormalDistribution[
    RandomReal[{-10, 10}, dim],
    RandomVariate[
     InverseWishartMatrixDistribution[dim + 1, IdentityMatrix[dim]]]
    ]
   ];

Calculate how the expected value of the second coordinate depends on the value of the first:

In[5]:=
Simplify@
 Mean @ ResourceFunction["ConditionedMultinormalDistribution"][
   randomDist, 1 -> \[FormalX][1], 2]
Out[5]=

Calculate the derivative:

In[6]:=
D[%, \[FormalX][1]]
Out[6]=

Condition on multiple indices and obtain the means of multiple marginals:

In[7]:=
Simplify@
 Mean @ ResourceFunction["ConditionedMultinormalDistribution"][
   randomDist, {1 -> \[FormalX][1], 2 -> \[FormalX][2]}, {3, 4}]
Out[7]=

Applications (3) 

Generate some (x,y) data:

In[8]:=
data = RandomVariate[BinormalDistribution[{0, 3}, {2, 1}, 0.7], 20];
ListPlot[data]
Out[9]=

Perform a simple linear fit by estimating the joint distribution of the data and then condition it on x:

In[10]:=
dist = Simplify@ResourceFunction["ConditionedMultinormalDistribution"][
   EstimatedDistribution[data, MultinormalDistribution[{\[Mu]1, \[Mu]2}, {{\[CapitalSigma]11, \[CapitalSigma]12}, {\[CapitalSigma]12, \[CapitalSigma]22}}]],
   1 -> \[FormalX],
   2]
Out[10]=

Plot the result:

In[11]:=
Show[
 Plot[Evaluate@InverseCDF[dist, {0.95, 0.5, 0.05}], {\[FormalX], -5, 5}, Filling -> {1 -> {3}}],
 ListPlot[data]]
Out[11]=

Properties and Relations (2) 

MultinormalDistribution normally converts SparseArray and StructuredArray objects to regular lists:

In[12]:=
sparseCovariance = SparseArray[{{i_, i_} :> 1, {1, 2} | {2, 1} -> 1/2}, {10, 10}];
MultinormalDistribution[sparseCovariance]
Out[13]=

Use Inactive to keep the covariance matrix packed as a sparse array:

In[14]:=
ResourceFunction["ConditionedMultinormalDistribution"][
  Inactive[MultinormalDistribution][sparseCovariance],
  1 -> 2
  ] // RepeatedTiming
Out[14]=

This is significantly more computationally efficient than having the covariance unpack into a regular list:

In[15]:=
ResourceFunction["ConditionedMultinormalDistribution"][
  MultinormalDistribution[sparseCovariance],
  1 -> 2
  ] // RepeatedTiming
Out[15]=

Conditioning on variables can be done with Conditioned, but it is less convenient and results in a general ProbabilityDistribution:

In[16]:=
dist1 = ProbabilityDistribution[
  {
   "CDF",
   Simplify@Probability[
     x1 < \[FormalY] \[Conditioned] x2 == a,
     {x1, x2} \[Distributed] MultinormalDistribution[{\[Mu]1, \[Mu]2}, {{\[CapitalSigma]11, \[CapitalSigma]12}, {\[CapitalSigma]12, \[CapitalSigma]22}}]
     ]
   },
  {\[FormalY], -\[Infinity], \[Infinity]}
  ]
Out[16]=

The same distribution with ConditionedMultinormalDistribution:

In[17]:=
dist2 = Simplify@
  ResourceFunction["ConditionedMultinormalDistribution"][
   MultinormalDistribution[{\[Mu]1, \[Mu]2}, {{\[CapitalSigma]11, \[CapitalSigma]12}, {\[CapitalSigma]12, \[CapitalSigma]22}}], 2 -> a, 1]
Out[17]=

The PDFs are the same up to a minus sign under the square:

In[18]:=
{
 PDF[dist1, x],
 PDF[dist2, x]
 }
Out[18]=

Publisher

Sjoerd Smit

Version History

  • 1.0.0 – 20 September 2019

Related Resources

License Information