it-swarm.com.de

Berechnung der Pearson-Korrelation und Signifikanz in Python

Ich suche nach einer Funktion, die zwei Listen als Eingabe aufnimmt und die Pearson-Korrelation und die Bedeutung der Korrelation zurückgibt.

150
ariel

Sie können einen Blick auf scipy.stats werfen:

from pydoc import help
from scipy.stats.stats import pearsonr
help(pearsonr)

>>>
Help on function pearsonr in module scipy.stats.stats:

pearsonr(x, y)
 Calculates a Pearson correlation coefficient and the p-value for testing
 non-correlation.

 The Pearson correlation coefficient measures the linear relationship
 between two datasets. Strictly speaking, Pearson's correlation requires
 that each dataset be normally distributed. Like other correlation
 coefficients, this one varies between -1 and +1 with 0 implying no
 correlation. Correlations of -1 or +1 imply an exact linear
 relationship. Positive correlations imply that as x increases, so does
 y. Negative correlations imply that as x increases, y decreases.

 The p-value roughly indicates the probability of an uncorrelated system
 producing datasets that have a Pearson correlation at least as extreme
 as the one computed from these datasets. The p-values are not entirely
 reliable but are probably reasonable for datasets larger than 500 or so.

 Parameters
 ----------
 x : 1D array
 y : 1D array the same length as x

 Returns
 -------
 (Pearson's correlation coefficient,
  2-tailed p-value)

 References
 ----------
 http://www.statsoft.com/textbook/glosp.html#Pearson%20Correlation
176
Sacha

Die Pearson-Korrelation kann mit corrcoef von Zahl berechnet werden.

import numpy
numpy.corrcoef(list1, list2)[0, 1]
94
winerd

Eine Alternative kann eine native Scipy-Funktion von linregress sein, die Folgendes berechnet:

steigung: Steigung der Regressionsgerade 

intercept: Intercept der Regressionsgeraden 

r-Wert: Korrelationskoeffizient

p-Wert: zweiseitiger p-Wert für einen Hypothesentest, dessen Nullhypothese lautet, dass die Steigung Null ist

stderr: Standardfehler der Schätzung

Und hier ist ein Beispiel:

a = [15, 12, 8, 8, 7, 7, 7, 6, 5, 3]
b = [10, 25, 17, 11, 13, 17, 20, 13, 9, 15]
from scipy.stats import linregress
linregress(a, b)

wird dich zurückbringen: 

LinregressResult(slope=0.20833333333333337, intercept=13.375, rvalue=0.14499815458068521, pvalue=0.68940144811669501, stderr=0.50261704627083648)
43
Salvador Dali

Wenn Sie keine Lust haben, Scipy zu installieren, habe ich diesen schnellen Hack verwendet, der von Programming Collective Intelligence modifiziert wurde - /:

(Für Korrektheit bearbeitet.)

from itertools import imap

def pearsonr(x, y):
  # Assume len(x) == len(y)
  n = len(x)
  sum_x = float(sum(x))
  sum_y = float(sum(y))
  sum_x_sq = sum(map(lambda x: pow(x, 2), x))
  sum_y_sq = sum(map(lambda x: pow(x, 2), y))
  psum = sum(imap(lambda x, y: x * y, x, y))
  num = psum - (sum_x * sum_y/n)
  den = pow((sum_x_sq - pow(sum_x, 2) / n) * (sum_y_sq - pow(sum_y, 2) / n), 0.5)
  if den == 0: return 0
  return num / den
34

Der folgende Code ist eine direkte Interpretation von der Definition :

import math

def average(x):
    assert len(x) > 0
    return float(sum(x)) / len(x)

def pearson_def(x, y):
    assert len(x) == len(y)
    n = len(x)
    assert n > 0
    avg_x = average(x)
    avg_y = average(y)
    diffprod = 0
    xdiff2 = 0
    ydiff2 = 0
    for idx in range(n):
        xdiff = x[idx] - avg_x
        ydiff = y[idx] - avg_y
        diffprod += xdiff * ydiff
        xdiff2 += xdiff * xdiff
        ydiff2 += ydiff * ydiff

    return diffprod / math.sqrt(xdiff2 * ydiff2)

Prüfung:

print pearson_def([1,2,3], [1,5,7])

kehrt zurück

0.981980506062

Dies stimmt mit Excel überein, diesem Rechner , SciPy (auch NumPy ), die 0,981980506 und 0,981980506619657 bzw. 0,98198050606196574 zurückgeben.

R :

> cor( c(1,2,3), c(1,5,7))
[1] 0.9819805

EDIT: Fehler behoben, auf den ein Kommentator hingewiesen hat.

29
dfrankow

Sie können dies auch mit pandas.DataFrame.corr tun:

import pandas as pd
a = [[1, 2, 3],
     [5, 6, 9],
     [5, 6, 11],
     [5, 6, 13],
     [5, 3, 13]]
df = pd.DataFrame(data=a)
df.corr()

Das gibt

          0         1         2
0  1.000000  0.745601  0.916579
1  0.745601  1.000000  0.544248
2  0.916579  0.544248  1.000000
20
Martin Thoma

Anstatt sich auf numpy/scipy zu verlassen, sollte meine Antwort am einfachsten zu codieren und die Schritte verstehen bei der Berechnung des Pearson-Korrelationskoeffizienten (PCC).

import math

# calculates the mean
def mean(x):
    sum = 0.0
    for i in x:
         sum += i
    return sum / len(x) 

# calculates the sample standard deviation
def sampleStandardDeviation(x):
    sumv = 0.0
    for i in x:
         sumv += (i - mean(x))**2
    return math.sqrt(sumv/(len(x)-1))

# calculates the PCC using both the 2 functions above
def pearson(x,y):
    scorex = []
    scorey = []

    for i in x: 
        scorex.append((i - mean(x))/sampleStandardDeviation(x)) 

    for j in y:
        scorey.append((j - mean(y))/sampleStandardDeviation(y))

# multiplies both lists together into 1 list (hence Zip) and sums the whole list   
    return (sum([i*j for i,j in Zip(scorex,scorey)]))/(len(x)-1)

Die Signifikanz von PCC soll Ihnen im Grunde zeigen, wie stark korreliert die beiden Variablen/Listen sind. Es ist wichtig zu beachten, dass der PCC-Wert im Bereich von von -1 bis 1 ..__ liegt. Ein Wert zwischen 0 und 1 bezeichnet eine positive Korrelation. _ Wert von 0 = höchste Variation (keinerlei Korrelation) Ein Wert zwischen -1 und 0 kennzeichnet eine negative Korrelation.

13
compski

Hmm, viele dieser Antworten haben langen und schwer lesbaren Code ...

Ich würde empfehlen, bei der Arbeit mit Arrays Numpy mit seinen schicken Funktionen zu verwenden:

import numpy as np
def pcc(X, Y):
   ''' Compute Pearson Correlation Coefficient. '''
   # Normalise X and Y
   X -= X.mean(0)
   Y -= Y.mean(0)
   # Standardise X and Y
   X /= X.std(0)
   Y /= Y.std(0)
   # Compute mean product
   return np.mean(X*Y)

# Using it on a random example
from random import random
X = np.array([random() for x in xrange(100)])
Y = np.array([random() for x in xrange(100)])
pcc(X, Y)
7

Hier ist eine Variante der Antwort von mkh, die viel schneller als sie läuft, und scipy.stats.pearsonr mit numba.

import numba

@numba.jit
def corr(data1, data2):
    M = data1.size

    sum1 = 0.
    sum2 = 0.
    for i in range(M):
        sum1 += data1[i]
        sum2 += data2[i]
    mean1 = sum1 / M
    mean2 = sum2 / M

    var_sum1 = 0.
    var_sum2 = 0.
    cross_sum = 0.
    for i in range(M):
        var_sum1 += (data1[i] - mean1) ** 2
        var_sum2 += (data2[i] - mean2) ** 2
        cross_sum += (data1[i] * data2[i])

    std1 = (var_sum1 / M) ** .5
    std2 = (var_sum2 / M) ** .5
    cross_mean = cross_sum / M

    return (cross_mean - mean1 * mean2) / (std1 * std2)
5

Hier ist eine Implementierung für die Pearson-Korrelation basierend auf einem spärlichen Vektor. Die Vektoren werden hier als Liste von Tupeln ausgedrückt als (Index, Wert). Die beiden spärlichen Vektoren können unterschiedlich lang sein, müssen aber über alle Vektorgrößen hinweg gleich sein. Dies ist nützlich für Text-Mining-Anwendungen, bei denen die Vektorgröße extrem groß ist, da die meisten Merkmale Wörterbündel sind. Daher werden Berechnungen normalerweise mit spärlichen Vektoren durchgeführt. 

def get_pearson_corelation(self, first_feature_vector=[], second_feature_vector=[], length_of_featureset=0):
    indexed_feature_dict = {}
    if first_feature_vector == [] or second_feature_vector == [] or length_of_featureset == 0:
        raise ValueError("Empty feature vectors or zero length of featureset in get_pearson_corelation")

    sum_a = sum(value for index, value in first_feature_vector)
    sum_b = sum(value for index, value in second_feature_vector)

    avg_a = float(sum_a) / length_of_featureset
    avg_b = float(sum_b) / length_of_featureset

    mean_sq_error_a = sqrt((sum((value - avg_a) ** 2 for index, value in first_feature_vector)) + ((
        length_of_featureset - len(first_feature_vector)) * ((0 - avg_a) ** 2)))
    mean_sq_error_b = sqrt((sum((value - avg_b) ** 2 for index, value in second_feature_vector)) + ((
        length_of_featureset - len(second_feature_vector)) * ((0 - avg_b) ** 2)))

    covariance_a_b = 0

    #calculate covariance for the sparse vectors
    for Tuple in first_feature_vector:
        if len(Tuple) != 2:
            raise ValueError("Invalid feature frequency Tuple in featureVector: %s") % (Tuple,)
        indexed_feature_dict[Tuple[0]] = Tuple[1]
    count_of_features = 0
    for Tuple in second_feature_vector:
        count_of_features += 1
        if len(Tuple) != 2:
            raise ValueError("Invalid feature frequency Tuple in featureVector: %s") % (Tuple,)
        if Tuple[0] in indexed_feature_dict:
            covariance_a_b += ((indexed_feature_dict[Tuple[0]] - avg_a) * (Tuple[1] - avg_b))
            del (indexed_feature_dict[Tuple[0]])
        else:
            covariance_a_b += (0 - avg_a) * (Tuple[1] - avg_b)

    for index in indexed_feature_dict:
        count_of_features += 1
        covariance_a_b += (indexed_feature_dict[index] - avg_a) * (0 - avg_b)

    #adjust covariance with rest of vector with 0 value
    covariance_a_b += (length_of_featureset - count_of_features) * -avg_a * -avg_b

    if mean_sq_error_a == 0 or mean_sq_error_b == 0:
        return -1
    else:
        return float(covariance_a_b) / (mean_sq_error_a * mean_sq_error_b)

Unit-Tests:

def test_get_get_pearson_corelation(self):
    vector_a = [(1, 1), (2, 2), (3, 3)]
    vector_b = [(1, 1), (2, 5), (3, 7)]
    self.assertAlmostEquals(self.sim_calculator.get_pearson_corelation(vector_a, vector_b, 3), 0.981980506062, 3, None, None)

    vector_a = [(1, 1), (2, 2), (3, 3)]
    vector_b = [(1, 1), (2, 5), (3, 7), (4, 14)]
    self.assertAlmostEquals(self.sim_calculator.get_pearson_corelation(vector_a, vector_b, 5), -0.0137089240555, 3, None, None)
4
Vipul Sharma

Dies ist eine Implementierung der Pearson-Korrelationsfunktion unter Verwendung von numpy:


def corr(data1, data2):
    "data1 & data2 should be numpy arrays."
    mean1 = data1.mean() 
    mean2 = data2.mean()
    std1 = data1.std()
    std2 = data2.std()

#     corr = ((data1-mean1)*(data2-mean2)).mean()/(std1*std2)
    corr = ((data1*data2).mean()-mean1*mean2)/(std1*std2)
    return corr
4

Pearson-Koeffizient-Berechnung mit Pandas in Python: Ich würde empfehlen, diesen Ansatz zu versuchen, da Ihre Daten Listen enthalten. Es ist einfach, mit Ihren Daten zu interagieren und sie von der Konsole aus zu bearbeiten, da Sie Ihre Datenstruktur visualisieren und nach Belieben aktualisieren können. Sie können den Datensatz auch exportieren, speichern und neue Daten zur späteren Analyse aus der Python-Konsole hinzufügen. Dieser Code ist einfacher und enthält weniger Codezeilen. Ich gehe davon aus, dass Sie ein paar kurze Zeilen Code benötigen, um Ihre Daten für die weitere Analyse zu überprüfen 

Beispiel:

data = {'list 1':[2,4,6,8],'list 2':[4,16,36,64]}

import pandas as pd #To Convert your lists to pandas data frames convert your lists into pandas dataframes

df = pd.DataFrame(data, columns = ['list 1','list 2'])

from scipy import stats # For in-built method to get PCC

pearson_coef, p_value = stats.pearsonr(df["list 1"], df["list 2"]) #define the columns to perform calculations on
print("Pearson Correlation Coefficient: ", pearson_coef, "and a P-value of:", p_value) # Results 

Sie haben Ihre Daten jedoch nicht für mich gepostet, um die Größe des Datensatzes oder die erforderlichen Transformationen vor der Analyse anzuzeigen. 

3
Web Ster

Sie können sich diesen Artikel ansehen. Dies ist ein gut dokumentiertes Beispiel für die Berechnung der Korrelation basierend auf historischen Forex-Währungspaardaten aus mehreren Dateien mithilfe der Pandabibliothek (für Python) und zum Erzeugen eines Heatmap-Diagramms mithilfe der Seaborn-Bibliothek.

http://www.tradinggeeks.net/2015/08/calculating-correlation-in-python/

1
Oleg K

Sie fragen sich vielleicht, wie Sie Ihre Wahrscheinlichkeit im Zusammenhang mit der Suche nach einer Korrelation in eine bestimmte Richtung (negative oder positive Korrelation) interpretieren können. Hier ist eine Funktion, die ich geschrieben habe, um Ihnen dabei zu helfen. Es könnte sogar richtig sein!

Es basiert auf Informationen, die ich aus http://www.vassarstats.net/rsig.html und http://en.wikipedia.org/wiki/Student%27s_t_distribution gefunden habe, dank anderer Antworten Hier.

# Given (possibly random) variables, X and Y, and a correlation direction,
# returns:
#  (r, p),
# where r is the Pearson correlation coefficient, and p is the probability
# that there is no correlation in the given direction.
#
# direction:
#  if positive, p is the probability that there is no positive correlation in
#    the population sampled by X and Y
#  if negative, p is the probability that there is no negative correlation
#  if 0, p is the probability that there is no correlation in either direction
def probabilityNotCorrelated(X, Y, direction=0):
    x = len(X)
    if x != len(Y):
        raise ValueError("variables not same len: " + str(x) + ", and " + \
                         str(len(Y)))
    if x < 6:
        raise ValueError("must have at least 6 samples, but have " + str(x))
    (corr, prb_2_tail) = stats.pearsonr(X, Y)

    if not direction:
        return (corr, prb_2_tail)

    prb_1_tail = prb_2_tail / 2
    if corr * direction > 0:
        return (corr, prb_1_tail)

    return (corr, 1 - prb_1_tail)
1
def pearson(x,y):
  n=len(x)
  vals=range(n)

  sumx=sum([float(x[i]) for i in vals])
  sumy=sum([float(y[i]) for i in vals])

  sumxSq=sum([x[i]**2.0 for i in vals])
  sumySq=sum([y[i]**2.0 for i in vals])

  pSum=sum([x[i]*y[i] for i in vals])
  # Calculating Pearson correlation
  num=pSum-(sumx*sumy/n)
  den=((sumxSq-pow(sumx,2)/n)*(sumySq-pow(sumy,2)/n))**.5
  if den==0: return 0
  r=num/den
  return r
0
Source

Ich habe dafür eine sehr einfache und leicht verständliche Lösung. Für zwei Arrays gleicher Länge kann der Pearson-Koeffizient einfach wie folgt berechnet werden: 

def manual_pearson(a,b):
"""
Accepts two arrays of equal length, and computes correlation coefficient. 
Numerator is the sum of product of (a - a_avg) and (b - b_avg), 
while denominator is the product of a_std and b_std multiplied by 
length of array. 
"""
  a_avg, b_avg = np.average(a), np.average(b)
  a_stdev, b_stdev = np.std(a), np.std(b)
  n = len(a)
  denominator = a_stdev * b_stdev * n
  numerator = np.sum(np.multiply(a-a_avg, b-b_avg))
  p_coef = numerator/denominator
  return p_coef
0
aumpen