Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Given a series of numbers for events X and Y, calculate Pearson's correlation coefficient. The probability of each event is equal, so expected values can be calculated by simply summing each series and dividing by the number of trials.

Input

1   6.86
2   5.92
3   6.08
4   8.34
5   8.7
6   8.16
7   8.22
8   7.68
9   12.04
10  8.6
11  10.96

Output

0.769

Shortest code wins. Input can be by stdin or arg. Output will be by stdout.

Edit: Builtin functions should not be allowed (ie calculated expected value, variance, deviation, etc) to allow more diversity in solutions. However, feel free to demonstrate a language that is well suited for the task using builtins (for exhibition).

Based on David's idea for input for Mathematica (86 char using builtin mean)

m=Mean;x=d[[All,1]];y=d[[All,2]];(m@(x*y)-m@x*m@y)/Sqrt[(m@(x^2)-m@x^2)(m@(y^2)-m@y^2)]

m = Mean;
x = d[[All,1]];
y = d[[All,2]];
(m@(x*y) - m@x*m@y)/((m@(x^2) - m@x^2)(m@(y^2) - m@y^2))^.5

Skirting by using our own mean (101 char)

m=Total[#]/Length[#]&;x=d[[All,1]];y=d[[All,2]];(m@(x*y)-m@x*m@y)/((m@(x^2)-m@x^2)(m@(y^2)-m@y^2))^.5

m = Total[#]/Length[#]&;
x = d[[All,1]];
y = d[[All,2]];
(m@(x*y)-m@x*m@y)/((m@(x^2)-m@x^2)(m@(y^2)-m@y^2))^.5
share|improve this question
    
Very nice streamlining of the Mathematica code, using your own mean! –  David Carraher Nov 29 '12 at 14:18
    
The MMa code can be shortened. See my comment under David's answer. Also, in your code you may define m=Total@#/Length@#& –  belisarius Dec 12 '12 at 12:12

6 Answers 6

up vote 1 down vote accepted

PHP 144 bytes

<?
for(;fscanf(STDIN,'%f%f',$$n,${-$n});$f+=${-$n++})$e+=$$n;
for(;$$i;$z+=$$i*$a=${-$i++}-=$f/$n,$y+=$a*$a)$x+=$$i*$$i-=$e/$n;
echo$z/sqrt($x*$y);

Takes the input from STDIN, in the format provided in the original post. Result:

0.76909044055492

Using the vector dot product:

where are the input vectors adjusted downwards by and respectively.

Perl 112 bytes

/ /,$e+=$`,$f+=$',@v=($',@v)for@u=<>;
$x+=($_-=$e/$.)*$_,$y+=($;=$f/$.-pop@v)*$;,$z-=$_*$;for@u;
print$z/sqrt$x*$y

0.76909044055492

Same alg, different language. In both cases, new lines have been added for 'readability', and are not required. The only notable difference in length is the first line: the parsing of input.

share|improve this answer

Mathematica

Here are a few ways to obtain the Pearson product moment correlation. They all produce the same result.

Built-in Correlation function I: 15 chars

This assumes that x and y are lists corresponding to each variable.

x~Correlation~y

0.76909


Built-in Correlation function II: 33 chars

This assumes d is a list of ordered pairs.

d[[All, 1]]~Correlation~d[[All, 2]]

0.76909


Relying on the Standard Deviation function: 118 chars

The correlation can be determined by:

s = StandardDeviation;
m = Mean;
n = Length[d];
x = d[[All, 1]];
y = d[[All, 2]];
Sum[((x[[i]] - m@x)/s@x) ((y[[i]] - m@y)/s@y), {i, n}]/(n - 1)

0.76909


Hand-rolled Correlation: 120 chars

Assuming x and y are lists...

s = Sum; n = Length[d]; m@p_ := Tr@p/n;
(s[(x[[i]] - m@x) (y[[i]] - m@y), {i, n}]/Sqrt@(s[(x[[i]] - m@x)^2, {i, n}] s[(y[[i]] - m@y)^2, {i, n}]))

0.76909

share|improve this answer
    
I get 0.076909 for the last code snippet. Also why do you have s = StandardDeviation; when s is never applied? –  miles t Nov 29 '12 at 8:03
    
Considering assumptions in answer for Q-language, in Mathematica it is just x~Correlation~y –  Vitaliy Kaurov Nov 29 '12 at 8:07
    
@VitaliyKaurov, Yes, good point, now taken into account. –  David Carraher Nov 29 '12 at 15:18
    
@milest. Of course! StandardDeviation was "legacy" from the earlier solutions. Think I'll reserve s for Sum. –  David Carraher Nov 29 '12 at 15:20
    
@milest The error in the final output was also due to /(n-1) being mistakenly carried over from the earlier solution. Now corrected. –  David Carraher Nov 29 '12 at 15:34

Q

Assuming builtins are allowed and x,y data are seperate vectors (7 chars):

x cor y

If data are stored as orderded pairs, as indicated by David Carraher, we get (for 12 characters):

{(cor).(+)x}
share|improve this answer
    
Don't correlation data normally consist of ordered pairs? –  David Carraher Nov 29 '12 at 2:51
    
I added al alternative for that case –  slackwear Nov 29 '12 at 3:41
    
+1 Nice. Thanks. –  David Carraher Nov 29 '12 at 4:24

J (55 char) (48 char)

   x=:1 2 3 4 5 6 7 8 9 10 11
   y=:6.86 5.92 6.08 8.34 8.7 8.16 8.22 7.68 12.04 8.6 10.96
   m=:+/%#
   ((m x*y)-m x*m y)%%:((m*:x)-*:m x)*(m*:y)-*:m y
   ((m@:*/@|:-*/@m)%%:@*/@(m@:*:-*:@m))x,.y (Gareth's contribution)
0.76909
share|improve this answer
    
You can factor out the x and y in the final line by stitching them together with ,. to give you ((m@:*/@|:-*/@m)%%:@*/@(m@:*:-*:@m))x,.y –  Gareth Nov 29 '12 at 23:34

APL 57

Using the dot product approach:

a←1 2 3 4 5 6 7 8 9 10 11

b←6.86 5.92 6.08 8.34 8.7 8.16 8.22 7.68 12.04 8.6 10.96

(a+.×b)÷((+/(a←a-(+/a)÷⍴a)*2)*.5)×(+/(b←b-(+/b)÷⍴b)*2)*.5

0.7690904406         
share|improve this answer

MATLAB/Octave

For the purpose of demonstrating built-ins only:

octave:1> corr(X,Y)
ans =  0.76909
octave:2> 
share|improve this answer

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.