# Calculate the correlation coefficient

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

• Very nice streamlining of the Mathematica code, using your own mean! – DavidC 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@#& – Dr. belisarius Dec 12 '12 at 12:12

## 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.

# Mathematica 34 bytes

Here are a few ways to obtain the Pearson product moment correlation. They all produce the same result. From Dr. belisarius: 34 bytes

Dot@@Normalize/@(#-Mean@#&)/@{x,y}


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: 31 chars

This assumes d is a list of ordered pairs.

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


0.76909

The use of ;; for All thanks to A Simmons.

Relying on the Standard Deviation function: 118 115 chars

The correlation can be determined by:

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


0.76909

Hand-rolled Correlation: 119 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

• I get 0.076909 for the last code snippet. Also why do you have s = StandardDeviation; when s is never applied? – miles 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. – DavidC Nov 29 '12 at 15:18
• @milest. Of course! StandardDeviation was "legacy" from the earlier solutions. Think I'll reserve s for Sum. – DavidC 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. – DavidC 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}

• Don't correlation data normally consist of ordered pairs? – DavidC Nov 29 '12 at 2:51
• I added al alternative for that case – skeevey Nov 29 '12 at 3:41

# MATLAB/Octave

For the purpose of demonstrating built-ins only:

octave:1> corr(X,Y)
ans =  0.76909
octave:2>


## 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


# J, 30 27 bytes

([:+/*%*&(+/)&.:*:)&(-+/%#)


This time as a function taking two arguments. Uses the vector formula for calculating it.

## Usage

   f =: ([:+/*%*&(+/)&.:*:)&(-+/%#)
(1 2 3 4 5 6 7 8 9 10 11) f (6.86 5.92 6.08 8.34 8.7 8.16 8.22 7.68 12.04 8.6 10.96)
0.76909


## Explanation

Takes two lists a and b as separate arguments.

([:+/*%*&(+/)&.:*:)&(-+/%#)  Input: a on LHS, b on RHS
&(     )  For a and b
#     Get the count
+/       Reduce using addition to get the sum
%      Divide the sum by the count to get the average
-         Subtract the initial value from the average
Now a and b have both been shifted by their average
For both a and b
*:             Square each value
(+/)&.:               Reduce the values using addition to get the sum
Apply in the inverse of squaring to take the square root
of the sum to get the norm
*&                    Multiply norm(a) by norm(b)
*                       Multiply a and b elementwise
%                      Divide a*b by norm(a)*norm(b) elementwise
[:+/                        Reduce using addition to the sum which is the
correlation coefficient and return it

• 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
• I have to admit, the code in itself looks gorgeous... speaking as someone who loves his non-alphanumeric code... ;) – Eliseo D'Annunzio Oct 6 '16 at 1:52
• There is a shorter 24 bytes version +/ .*&(%+/&.:*:)&(-+/%#) recognized by Oleg on the J forums. – miles Jul 11 '17 at 3:48

## Python 3, 140 bytes

E=lambda x:sum(x)/len(x)
S=lambda x:(sum((E(x)-X)**2for X in x)/len(x))**.5
lambda x,y:E([(X-E(x))*(Y-E(y))for X,Y in zip(x,y)])/S(x)/S(y)


2 helper functions (E and S, for expected value and standard deviation, respectively) are defined. Input is expected as 2 iterables (lists, tuples, etc). Try it online.

# Oracle SQL 11.2, 152 bytes (for exhibition)

SELECT CORR(a,b)FROM(SELECT REGEXP_SUBSTR(:1,'[^ ]+',1,2*LEVEL-1)a,REGEXP_SUBSTR(:1,'[^ ]+',1,2*LEVEL)b FROM DUAL CONNECT BY INSTR(:1,' ',2,LEVEL-1)>0);


Un-golfed

SELECT CORR(a,b)
FROM
(
SELECT REGEXP_SUBSTR(:1, '[^ ]+', 1, 2*LEVEL-1)a, REGEXP_SUBSTR(:1, '[^ ]+', 1, 2*LEVEL)b
FROM DUAL
CONNECT BY INSTR(:1, ' ', 2, LEVEL - 1) > 0
)


Input string should use the same decimal separator as the database.

# Python 3 with SciPy, 52 bytes (for exhibition)

from scipy.stats import*
lambda x,y:pearsonr(x,y)


An anonymous function that takes input of the two data sets as lists x and y, and returns the correlation coefficient.

How it works

There's not a lot going on here; SciPy has a builtin that returns both the coefficient and the p-value for testing non-correlation, so the function simply passes the data sets to this and returns the first element of the (coefficient, p-value)` tuple returned by the builtin.

Try it on Ideone