Pearson-correlatie en -betekenis berekenen in Python

Ik ben op zoek naar een functie die als invoer twee lijsten nodig heeft en de Pearson-correlatie, en de betekenis van de correlatie.


Antwoord 1, autoriteit 100%

Je kunt een kijkje nemen op scipy.stats:

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

Antwoord 2, autoriteit 58%

De Pearson-correlatie kan worden berekend met numpy’s corrcoef.

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

Antwoord 3, autoriteit 28%

Een alternatief kan een native scipy-functie zijn van linregressdie berekent:

helling: helling van de regressielijn

intercept : intercept van de regressielijn

r-waarde: correlatiecoëfficiënt

p-waarde : tweezijdige p-waarde voor een hypothesetest waarvan de nulhypothese is dat de helling nul is

stderr: standaardfout van de schatting

En hier is een voorbeeld:

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)

zal je teruggeven:

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

Antwoord 4, autoriteit 18%

Als je geen zin hebt om scipy te installeren, heb ik deze snelle hack gebruikt, enigszins aangepast van Programming Collective Intelligentie:

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(xi*xi for xi in x)
  sum_y_sq = sum(yi*yi for yi in y)
  psum = sum(xi*yi for xi, yi in zip(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

Antwoord 5, Autoriteit 16%

De volgende code is een rechte interpretatie van de definitie :

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)

Test:

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

Retourneren

0.981980506062

Dit is het eens met Excel, deze rekenmachine , Scipy (ook Numpy ), die respectievelijk 0.981980506 en 0.9819805060619657 en 0.98198050606196574.

r :

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

EDIT: een bug verholpen die werd opgemerkt door een commentator.


Antwoord 6, autoriteit 13%

Je kunt dit doen met pandas.DataFrame.corrook:

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

Dit geeft

         0         1         2
0  1.000000  0.745601  0.916579
1  0.745601  1.000000  0.544248
2  0.916579  0.544248  1.000000

Antwoord 7, autoriteit 5%

In plaats van te vertrouwen op numpy/scipy, denk ik dat mijn antwoord het gemakkelijkst te coderen is en de stappen moet begrijpenbij het berekenen van de Pearson-correlatiecoëfficiënt (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)

De betekenisvan PCC is in feite om u te laten zien hoe sterk gecorreleerdde twee variabelen/lijsten zijn.
Het is belangrijk op te merken dat de PCC-waarde varieert van van -1 tot 1.
Een waarde tussen 0 en 1 duidt op een positieve correlatie.
Waarde van 0 = hoogste variatie (geen enkele correlatie).
Een waarde tussen -1 en 0 duidt op een negatieve correlatie.


Antwoord 8, autoriteit 5%

Pearson-coëfficiëntberekening met panda’s in python:
Ik zou willen voorstellen om deze aanpak te proberen, omdat uw gegevens lijsten bevatten. Het zal gemakkelijk zijn om met uw gegevens te communiceren en deze vanaf de console te manipuleren, aangezien u uw gegevensstructuur kunt visualiseren en naar wens kunt bijwerken. U kunt de gegevensset ook exporteren en opslaan en nieuwe gegevens uit de Python-console toevoegen voor latere analyse. Deze code is eenvoudiger en bevat minder regels code. Ik neem aan dat je een paar snelle regels code nodig hebt om je gegevens te screenen voor verdere analyse

Voorbeeld:

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 

U heeft uw gegevens echter niet gepost zodat ik de grootte van de gegevensset of de transformaties die mogelijk nodig zijn vóór de analyse, kan zien.


Antwoord 9, autoriteit 3%

Hmm, veel van deze reacties hebben lange en moeilijk leesbare code…

Ik raad aan om numpy te gebruiken met zijn handige functies bij het werken met arrays:

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)

Antwoord 10, autoriteit 3%

Dit is een implementatie van de Pearson Correlation-functie met behulp van 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


Antwoord 11, autoriteit 3%

Hier is een variant op het antwoord van mkh die veel sneller werkt dan deze, en scipy.stats.pearsonr, met 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)

Antwoord 12

Hier is een implementatie voor peerson-correlatie op basis van sparse vector. De vectoren hier worden uitgedrukt als een lijst van tupels uitgedrukt als (index, waarde). De twee schaarse vectoren kunnen van verschillende lengte zijn, maar over het algemeen moet de grootte van de vector hetzelfde zijn. Dit is handig voor tekstmining-toepassingen waar de vectorgrootte extreem groot is omdat de meeste functies een woordverzameling zijn en daarom worden berekeningen meestal uitgevoerd met behulp van schaarse vectoren.

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)

Eenheidstests:

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)

Antwoord 13

Ik heb hier een heel eenvoudige en gemakkelijk te begrijpen oplossing voor. Voor twee arrays van gelijke lengte kan de Pearson-coëfficiënt eenvoudig als volgt worden berekend:

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

Antwoord 14

Je vraagt je misschien af hoe je je waarschijnlijkheid moet interpreteren in de context van het zoeken naar een correlatie in een bepaalde richting (negatieve of positieve correlatie.) Hier is een functie die ik heb geschreven om daarbij te helpen. Het zou zelfs kunnen kloppen!

Het is gebaseerd op informatie die ik heb verzameld van http://www.vassarstats.net/rsig.htmlen http://en.wikipedia.org/wiki/Student%27s_t_distribution, dankzij andere antwoorden die hier zijn gepost.

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

Antwoord 15

Je kunt dit artikel bekijken. Dit is een goed gedocumenteerd voorbeeld voor het berekenen van correlatie op basis van historische forex-valutaparengegevens uit meerdere bestanden met behulp van de panda-bibliotheek (voor Python), en vervolgens het genereren van een heatmap-plot met behulp van de Seaborn-bibliotheek.

http://www.tradinggeeks.net/2015/08 /correlatie-berekenen-in-python/


Antwoord 16

Vanaf Python 3.10release schedule, de correlatiecoëfficiënt van Pearson (statistics.correlation) is direct beschikbaar in de standaardbibliotheek:

from statistics import correlation
# a = [15, 12, 8, 8, 7, 7, 7, 6, 5, 3]
# b = [10, 25, 17, 11, 13, 17, 20, 13, 9, 15]
correlation(a, b)
# 0.1449981545806852

Antwoord 17

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

Other episodes