Calcular o coeficiente de correlação

9

Dada uma série de números para os eventos X e Y, calcule o coeficiente de correlação de Pearson. A probabilidade de cada evento é igual; portanto, os valores esperados podem ser calculados simplesmente somando cada série e dividindo pelo número de tentativas.

Entrada

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

Resultado

0.769

O menor código vence. A entrada pode ser feita por stdin ou arg. A saída será por stdout.

Editar: Funções internas não devem ser permitidas (ou seja, valor esperado calculado, variação, desvio, etc.) para permitir mais diversidade nas soluções. No entanto, sinta-se à vontade para demonstrar um idioma adequado para a tarefa usando os recursos internos (para exibição).

Com base na idéia de David para entrada no Mathematica (86 caracteres usando a média incorporada)

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

Contornando usando nossa própria média (101 caracteres)

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
milhas
fonte
Otimização muito agradável do código do Mathematica, usando seu próprio meio!
31412
O código MMa pode ser reduzido. Veja meu comentário na resposta de David. Além disso, em seu código, você pode definirm=Total@#/Length@#&
Dr. belisarius

Respostas:

3

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);

Recebe a entrada de STDIN, no formato fornecido na postagem original. Resultado:

0.76909044055492

Usando o produto de pontos vetoriais:

onde os vetores de entrada são ajustados para baixo por e respectivamente.

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

Mesmo alg, idioma diferente. Nos dois casos, novas linhas foram adicionadas para 'legibilidade' e não são necessárias. A única diferença notável no comprimento é a primeira linha: a análise da entrada.

primo
fonte
5

Mathematica 34 bytes

Aqui estão algumas maneiras de obter a correlação do momento do produto Pearson. Todos eles produzem o mesmo resultado. Do Dr. belisarius: 34 bytes

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

Função de Correlação Integrada I : 15 caracteres

Isso pressupõe que xe ysão listas correspondentes a cada variável.

x~Correlation~y

0,76909


Função de correlação interna II : 31 caracteres

Isso pressupõe que d é uma lista de pares ordenados.

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

0,76909

O uso de ;;para Allgraças a A Simmons.


Confiando na função de desvio padrão : 118 115 caracteres

A correlação pode ser determinada por:

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


Correlação enrolada à mão : 119 caracteres

Assumindo xe ysão listas ...

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

DavidC
fonte
Recebo 0,076909 para o último trecho de código. Também porque você tem s = StandardDeviation; quando s nunca é aplicado?
milhas
Considerando os pressupostos em resposta para Q-language, em Mathematica é apenas x ~ Correlação ~ y
Vitaliy Kaurov
@VitaliyKaurov, Sim, bom ponto, agora levado em consideração.
31412
@milest. Claro! O StandardDeviation era "herdado" das soluções anteriores. Acho que vou reservar spara Sum.
31412
@milest O erro na saída final também ocorreu devido a /(n-1)uma transferência incorreta da solução anterior. Agora corrigido.
29412
2

Q

Supondo que os buildins são permitidos ex, os dados x, y são vetores separados (7 caracteres):

x cor y

Se os dados são armazenados como pares ordenados, conforme indicado por David Carraher, obtemos (para 12 caracteres):

{(cor).(+)x}
skeevey
fonte
Os dados de correlação normalmente não consistem em pares ordenados?
31412
Eu adicionado al alternativa para esse caso
skeevey
2

MATLAB / Octave

Com o objetivo de demonstrar apenas os integrados:

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

APL 57

Usando a abordagem do produto escalar:

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         
Graham
fonte
2

J, 30 27 bytes

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

Desta vez, como uma função, tendo dois argumentos. Usa a fórmula do vetor para calculá-lo.

Uso

   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

Explicação

Toma duas listas um e b como argumentos separados.

([:+/*%*&(+/)&.:*:)&(-+/%#)  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
milhas
fonte
Você pode fatorar o xe yna linha final por costura-los juntos com ,.a dar-lhe((m@:*/@|:-*/@m)%%:@*/@(m@:*:-*:@m))x,.y
Gareth
Eu tenho que admitir, o código em si parece lindo ... falando como alguém que ama o seu código não-alfanumérico ...;)
Wally West
Há uma versão mais curta 24 bytes +/ .*&(%+/&.:*:)&(-+/%#)reconhecido por Oleg nas J fóruns .
miles
1

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 funções auxiliares ( Ee S, para o valor esperado e desvio padrão, respectivamente) são definidas. A entrada é esperada como 2 iteráveis ​​(listas, tuplas, etc.). Experimente online .

Mego
fonte
1

Oracle SQL 11.2, 152 bytes (para exibição)

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);

Sem golfe

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
)

A sequência de entrada deve usar o mesmo separador decimal que o banco de dados.

Jeto
fonte
1

Python 3 com SciPy, 52 bytes (para exibição)

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

Uma função anônima que leva a entrada dos dois conjuntos de dados como listas xe y, e retorna o coeficiente de correlação.

Como funciona

Não há muita coisa acontecendo aqui; O SciPy possui um built-in que retorna o coeficiente e o valor-p para testar a não-correlação; portanto, a função simplesmente passa os conjuntos de dados para ele e retorna o primeiro elemento da (coefficient, p-value)tupla retornada pelo built-in.

Experimente no Ideone

TheBikingViking
fonte