Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

This question is a follow-up from here. I have a function that generates a list of correlations between some random variables:

varparams = Table[i, {i, 0.1, 0.9, 0.1}];

var[i_] := 
 RandomChoice[{varparams[[i]], 1 - varparams[[i]]} -> {1, 0}, 10]

corrcheck[i_, j_, n_] := 
 Table[BlockRandom[SeedRandom[k];  
    Correlation[var[i], var[j]]], {k, n}]

Now, if by chance one or both of var[i],var[j] is a list of all 1's, then Correlation[var[i],var[j]] is undefined. I want to improve corrcheck[i_, j_, n_] so that it automatically throws away all such vars. My idea was to do something like this:

corrcheck[i_, j_, n_] := 
 Table[BlockRandom[SeedRandom[k]; 
   If[Mean@var[i] != 1 && Mean@var[j] != 1, 
    Correlation[var[i], var[j]], "N/A"]], {k, n}]

Why doesn't this work? Have I missed a better alternative?

Thanks in advance.

share|improve this question
add comment

2 Answers 2

up vote 4 down vote accepted

A minor issue with your current test is that it ignores the case where Mean[var[i]]=0. You need to use Variance[var[i]] in your condition.

However, this does not fix the real problem. The real issue with the current formulation is that randomization is performed everytime var[i] is used. Because of this, when you check Variance[var[i]] !=0 and then later use var[i] in Correlation[var[i]],var[j]] there are actually two different var[i]s, and sometimes the first one passes your check but the second one inside Correlation has zero standard deviation. To fix this you need to use something like

 ClearAll[corrcheck];
 corrcheck[i_, j_, n_] := 
 Table[BlockRandom[SeedRandom[k]; With[{v1 = var[i], v2 = var[j]},
 If[Variance@v1 != 0 && Variance@v2 != 0, Correlation[v1, v2], "N/A"]]], {k, n}]

where in each iteration one random value is generated to be used for checking non-zero variance and computing the correlation for each var[i].

EDIT: Few more alternative ways to define corrcheck

ClearAll[corrcheck2, corrcheck3];
corrcheck2[i_, j_, n_] := Table[BlockRandom[SeedRandom[k]; 
    Module[{v1, v2}, If[Variance@v1 != 0 && Variance@v2 != 0, Correlation[v1, v2], 
   "N/A"] /. {v1 -> var[i], v2 -> var[j]}]], {k, n}];
corrcheck3[i_, j_, n_] :=   Table[BlockRandom[SeedRandom[k]; 
  If[Variance@#1 != 0 && Variance@#2 != 0, Correlation[#1, #2], 
   "N/A"] &[var[i], var[j]]], {k, n}];
corrcheck[1, 2, 10]
(* {"N/A","N/A",-0.21821789,"N/A",0.21821789,-0.408248290,
   -0.1111111,-0.3333333,-0.218217,"N/A"}*)
corrcheck2[1, 2, 10] == corrcheck3[1, 2, 10] == corrcheck[1, 2, 10]
(* True *)

EDIT: Cleanest approach is to make use of Correlation's internal testing for zero standard deviation -- using Check as in Mark's answer but placing it just outside Correlation:

corrcheckX[i_, j_, n_] := Table[BlockRandom[SeedRandom[k];
 Quiet[ Check[Correlation[var[i], var[j]], "N/A", Correlation::zerosd]]], {k, n}];
corrcheck2[1, 2, 10]==corrcheck3[1, 2, 10]==corrcheck[1, 2, 10] == corrcheckX[1, 2, 10]
(* True *)
share|improve this answer
    
Okay, now we're cooking, but (correct me if I misunderstand your code) it seems I would have to ClearAll[corrcheck] every time I want to call `corrcheck[i,j,n]. Is there a way to include ClearAll in the function itself? –  Ooku Sep 27 '12 at 22:55
    
@Ooku, you don't need to use ClearAll[...] everytime you use corrcheck[i,j,n]. You need to use clear only once before you define corrcheck - just in case you previously used the symbol corrcheck with other specifications during the current mma session. –  kguler Sep 27 '12 at 23:00
    
Oh, right. Thanks a lot for the prompt reply, btw! –  Ooku Sep 27 '12 at 23:05
    
@Ooku, my pleasure. Welcome to Mma.SE. –  kguler Sep 27 '12 at 23:09
add comment

I guess you could use Check to check for the error message and return some symbol or string indicating the failure

corrcheck[i_, j_, n_] := Quiet[Check[
 Table[BlockRandom[SeedRandom[k];  
  Correlation[var[i], var[j]]], {k, n}],
  "bad",Correlation::zerosd]];

Now

result = {corrcheck[8,8,1], corrcheck[8,8,2]} // InputForm
(* Out: {{-(1/Sqrt[21])}, "bad"} *)

Afterwards, you could call DeleteCases[result, "bad"] to delete the bad stuff.

share|improve this answer
    
That works after a fashion, but it maps entire sets of correlations -> bad, instead of just one of the set. –  Ooku Sep 27 '12 at 16:44
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.