# A partial outer product

Here is an example of what I want to do:

Suppose I have a collection of samples S = {s1, s2, s3, ...}. I want to construct the correlation matrix (and yes, this might already be built in, but this is just an example). The obvious way of doing this is by doing Outer[Correlation, S, S], but obviously this does (slightly more than) twice the amount of work necessary. There are ugly ways to fix this, for example, defining a function

 corr[i_, j_]:= If[i>j, Correlation[S[[i]], S[[j]]], 0]


but this does not appeal (and it is also space-wasteful). Is there an elegant solution?

• In other words, are you trying to more efficiently implement Outer[ #1, #2, #2]&? Or is your question more specific? Apr 29, 2017 at 18:28
• @jjc385 I am trying to do things more efficiently when the function is symmetric in the arguments, so one does not do the computation twice over. Apr 29, 2017 at 18:39
• @IgorRivin does my answer work. If not let me know so that i can delete it ! Apr 29, 2017 at 18:40
• @Igor Ah, yes, of course the function needs to be symmetric in the arguments. Is it possible Outer does this automatically when its first argument is Orderless? Apr 29, 2017 at 18:41
• @AliHashmi Yes, that does work, but it is not so different from what I suggest Maybe there is only one real way to do this.... Apr 29, 2017 at 19:35

S = {s1, s2, s3, s4};
ls = SparseArray[{i_, j_} :> Correlation[S[[i]], S[[j]]] /; i > j,
ConstantArray[Length@S,2]] // Quiet;

ls//Normal

(* {{0, 0, 0, 0}, {Correlation[s2, s1], 0, 0, 0}, {Correlation[s3, s1],
Correlation[s3, s2], 0, 0}, {Correlation[s4, s1],
Correlation[s4, s2], Correlation[s4, s3], 0}} *)


this is same as:

ls = Outer[Correlation, S, S] // Quiet;
Do[If[i <= j, ls[[i, j]] = 0], {i, 4}, {j, 4}];
ls
(* {{0, 0, 0, 0}, {Correlation[s2, s1], 0, 0, 0}, {Correlation[s3, s1],
Correlation[s3, s2], 0, 0}, {Correlation[s4, s1],
Correlation[s4, s2], Correlation[s4, s3], 0}} *)