Soru Python'da Pearson korelasyon ve öneminin hesaplanması


Ben iki liste olarak alır bir işlev arıyorum ve döndürür Pearson korelasyonve korelasyonun önemi.


135
2017-10-16 14:15


Menşei




Cevaplar:


Bir göz atabilirsin 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

164
2017-10-16 14:29



İki sözlük arasındaki korelasyon katsayısına ne dersiniz? - user702846
@ user702846 Pearson korelasyon 2xN matrisinde tanımlanmıştır. İki sözlükleri 2xN matrisine dönüştüren genellikle geçerli bir yöntem yoktur, ancak sözlüklerinizin anahtarlarının kesişimine karşılık gelen sözlük değerleri çiftleri dizisini kullanabilirsiniz. - winerd


Pearson korelasyonu numpy ile hesaplanabilir. corrcoef.

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

78
2018-04-16 00:17



Çalışır - ama oldukça kafa karıştırıcı çıktı. Aşağıdaki @Salvador Dali cevabını kontrol edin;) - dmeu
çıktı kafa karıştırıcı, ama aslında çok basit. bu açıklamayı kontrol et stackoverflow.com/a/3425548/1245622 - linqu


Bir alternatif, yerel bir scipy işlevi olabilir. linregress hangi hesaplar:

eğim: regresyon hattının eğimi

kesişme: regresyon hattının kesilmesi

r-değeri: korelasyon katsayısı

p değeri: sıfır hipotezi eğim sıfır olan bir hipotez testi için iki taraflı p değeri

stderr: Tahminin standart hatası

Ve burada bir örnek:

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)

size geri dönecek:

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

38
2017-11-21 13:10



Büyük cevap - şimdiye kadar en bilgilendirici. Ayrıca iki sıralı pandalarla çalışır.DataFrame: lineregress(two_row_df) - dmeu


Scipy'yi yüklemek istemezseniz, birazdan değiştirilen bu hızlı hack'i kullandım. Toplu İstihbarat Programlama:

(Doğruluk için düzenlenmiştir.)

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

32
2018-04-19 08:52



Bunun Excel, NumPy ve R. ile aynı fikirde olmadığını fark ettim. stackoverflow.com/questions/3949226/.... - dfrankow
Başka bir yorumcu belirttiği gibi, bu bir float / int hatasında. Ben sum_y / n ints için tamsayı bölümü olduğunu düşünüyorum. Eğer sum_x = float (sum (x)) ve sum_y = float (sum (y)) kullanırsanız, çalışır. - dfrankow
@dfrankow Bence imap yüzer işleyemez çünkü. python bir verir TypeError: unsupported operand type(s) for -: 'itertools.imap' and 'float' en num = psum - (sum_x * sum_y/n) - alvas
Bir stil notu olarak Python haritanın bu gereksiz kullanımının üzerine atıyor (liste kavramaları lehine) - Maxim Khesin
Yorum olarak, scipy ve diğerleri gibi kütüphanelerin çok sayıda sayısal analiz yapan insanlar tarafından geliştirildiğini düşünün. Bu, birçok yaygın tuzaktan kaçınmanızı sağlayabilir (örneğin, X veya Y'de çok büyük ve çok az sayıya sahip olmak, felaketle sonuçlanabilir) - geekazoid


Aşağıdaki kod, düz bir yorumudur. tanımı:

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)

Ölçek:

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

döner

0.981980506062

Bu Excel ile hemfikir, bu hesap, scipy (Ayrıca NumPy), sırasıyla 0.981980506 ve 0.9819805060619657 ve 0.98198050606196574.

R,:

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

DÜZENLE: Bir yorumcu tarafından işaret edilen bir hata düzeltildi.


28
2018-01-29 11:28



Değişkenlerin tipine dikkat edin! Bir int / float problemi ile karşılaştınız. İçinde sum(x) / len(x) siz insize edersiniz, yüzen değil. Yani sum([1,5,7]) / len([1,5,7]) = 13 / 3 = 4tamsayı bölüme göre (istediğinizde) 13. / 3. = 4.33...). Düzeltmek için bu satırı şu şekilde yeniden yazınız: float(sum(x)) / float(len(x)) (Python otomatik olarak dönüştürdüğü için bir yüzer yeterlidir). - Piotr Migdal
Teşekkürler! Sabit.. - dfrankow
Kodunuz aşağıdaki gibi durumlar için çalışmaz: [10,10,10], [0,0,0] veya [10,10], [10,0]. hatta [10,10], [10,10] - madCode
Bu vakalardan herhangi biri için korelasyon katsayısı tanımlanmamıştır. Onları R içine koymak, her üç için de "NA" değerini döndürür. - dfrankow


Bunu ile yapabilirsiniz pandas.DataFrame.corr, ayrıca:

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

Bu verir

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

15
2018-06-30 11:39



çok yararlı!!! - Hemaa mathavan
Bu önemsiz bir ilişkidir. - Ivelin


Numpy / scipy'ye güvenmek yerine, cevabımın en kolay kod ve adımları anlamak Pearson Korelasyon Katsayısının (PCC) hesaplanması.

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)

önem PCC temelde nasıl olduğunu göstermek için kuvvetle ilişkili iki değişken / liste vardır. PCC değeri aralıkları not etmek önemlidir -1'den 1'e. 0 ila 1 arasında bir değer pozitif bir korelasyon anlamına gelir. 0 = en yüksek değişim değeri (herhangi bir korelasyon yok). -1 ila 0 arasında bir değer negatif bir korelasyon anlamına gelir.


13
2017-10-31 15:28



Python'un bir yerleşimi olduğunu unutmayın. sum işlevi. - bfontaine
500'den fazla değerle 2 listelerinde inanılmaz bir karmaşıklığa ve yavaş performansa sahiptir. - Nikolay Fominyh


Hmm, bu cevapların çoğunun kodu okumak uzun ve zor ...

Dizilerle çalışırken şık özellikleriyle numpy'yi kullanmanızı öneririm:

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
2017-09-15 20:19



Bu cevabı çok beğenmeme rağmen, işlevin içinde hem X hem de Y'yi kopyala / kopyalamanızı tavsiye ederim. Aksi halde her ikisi de değiştirilir, bu da istenen bir davranış olmayabilir. - antonimmo


İşte seyrek vektör dayalı pearson korelasyon için bir uygulama. Buradaki vektörler (indeks, değer) olarak ifade edilen tupllerin bir listesi olarak ifade edilir. İki seyrek vektörler farklı uzunluklarda olabilir, ancak tüm vektör boyutlarının aynı olması gerekecektir. Bu, metin büyüklüğü uygulamaları için yararlıdır, çünkü çoğu özellik kelimelerin büyüklüğü nedeniyle vektör büyüklüğü çok büyüktür ve dolayısıyla hesaplamalar genellikle seyrek vektörler kullanılarak gerçekleştirilir.

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)

Birim testleri:

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
2018-03-02 21:13





Bu, numpy kullanarak Pearson Korelasyon işlevinin bir uygulamasıdır:


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
2018-03-22 12:55