16 Soru: Python'da Pearson korelasyonu ve öneminin hesaplanması

tarafından oluşturulan soru Sat, Nov 22, 2014 12:00 AM

İki giriş listesi gibi bir işlevi arıyorum ve Pearson korelasyonunu döndüren bir işlev arıyorum a> ve korelasyonun önemi.

    
168
16 Yanıtlar                              16                         

scipy.stats adresine bir göz atabilirsiniz:

 
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
    
187
2017-04-05 18: 44: 25Z
  1. İki sözlükteki korelasyon katsayısına ne dersiniz ?!
    2013-05-22 23: 49: 39Z
  2. @ user702846 Pearson korelasyonu 2xN'lik bir matriste tanımlanır. İki sözlükçiyi 2xN matrisine dönüştüren genel olarak uygulanabilir bir yöntem yoktur, ancak sözlüklerinizin anahtarlarının kesişimindeki tuşlara karşılık gelen bir çift sözlük değeri dizisi kullanabilirsiniz.
    2015-08-18 09: 23: 29Z

Pearson korelasyonu numpy’nin corrcoef ile hesaplanabilir >.

 
import numpy
numpy.corrcoef(list1, list2)[0, 1]
    
99
2016-09-09 13: 54: 53Z
  1. İşler - ama oldukça kafa karıştırıcı çıktı. @Salvador Dali'nin yanıtını aşağıda görebilirsiniz;)
    2016-03-09 10: 10: 33Z
  2. çıktı kafa karıştırıcı, ama aslında çok basit. bu açıklamayı kontrol et stackoverflow.com/a/3425548/1245622
    2017-12-20 09: 21: 44Z

Bir alternatif, linregress hangi hesaplar:

  

eğim: regresyon çizgisinin eğimi

     

kesişme: regresyon çizgisinin kesilmesi

     

r değeri: korelasyon katsayısı

     

p değeri: boş hipotezi eğimin sıfır olduğu bir hipotez testi için iki taraflı p değeri

     

stderr: Tahminin standart hatası

Ve işte 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)
    
48
2015-11-21 13: 10: 00Z
  1. Harika cevap - çok bilgilendirici. Ayrıca iki sıralı pandalarla da çalışır.DataFrame: lineregress(two_row_df)
    2016-03-09 10: 09: 54Z

Scipy kurmak istemiyorsanız, bu hızlı kesmeyi kullandım, Kolektif Zekayı Programlama :

(Doğruluk için düzenlendi.)

 
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
2011-10-30 20: 41: 10Z
  1. Bunun Excel, NumPy ve R ile uyumsuzluğunu keşfetmesine şaşırdım. Bkz. stackoverflow.com/questions/3949226/… .
    2011-10-29 13: 48: 16Z
  2. Başka bir yorumcunun işaret ettiği gibi, bunun float /int hatası var. Bence sum_y /n, ints için tamsayıdır. Sum_x = float (sum (x)) ve sum_y = float (sum (y)) kullanırsanız çalışır.
    2011-10-30 20: 05: 26Z
  3. @ dfrankow Bunun imap float'ı kaldıramadığı için olduğunu düşünüyorum. python, TypeError: unsupported operand type(s) for -: 'itertools.imap' and 'float'’da num = psum - (sum_x * sum_y/n) verir
    2013-01-24 14: 17: 26Z
  4. Stil notu olarak Python, bu gereksiz harita kullanımından kaçınır (liste kavramaların lehine)
    2013-11-22 20: 58: 45Z
  5. Bir yorum olarak, scipy ve diğerleri gibi kütüphanelerin çok sayıda sayısal analiz bilen insanlar tarafından geliştirildiğini düşünün. Bu, pek çok ortak tuzaktan kaçınmanıza neden olabilir (örneğin, X veya Y’de çok büyük ve çok az sayıların olması felaketle sonuçlanmaya neden olabilir)
    2014-09-30 22: 28: 35Z

Aşağıdaki kod, tanımın doğru bir yorumudur:  

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

döner

 
0.981980506062

Bu, Excel ile aynı fikirdedir, bu hesap makinesi , SciPy (ayrıca NumPy ), sırasıyla 0.981980506 ve 0.9819805060619657 ve 0.98198050606196574'ü döndürür.

R :

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

EDIT : Bir yorumcunun gösterdiği bir hata düzeltildi.

    
30
2014-03-09 03: 04: 53Z
  1. Değişkenlerin türüne dikkat edin! Bir int /float sorunu ile karşılaştınız. sum(x) / len(x)'da yüzenleri bölmezsiniz, bölmeleri bölersiniz. Yani sum([1,5,7]) / len([1,5,7]) = 13 / 3 = 4, tamsayıya göre (13. / 3. = 4.33...'u istiyorsan). Düzeltmek için bu satırı float(sum(x)) / float(len(x)) olarak yeniden yazın (Python otomatik olarak dönüştürdüğü için bir kayan nokta yeterlidir).
    2011-10-30 19: 46: 16Z
  2. Teşekkürler! Sabit ..
    2011-10-30 20: 05: 43Z
  3. Kodunuz: [10,10,10], [0,0,0] veya [10,10], [10, 0]. hatta [10,10], [10,10]
    2012-05-18 16: 56: 06Z
  4. Korelasyon katsayısı bu durumlar için tanımlanmadı. Bunları R'ye koymak, üçünün tümü için "NA" döndürür.
    2012-05-18 17: 55: 39Z

Bunu pandas.DataFrame.corr ile yapabilirsiniz , 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
    
23
2017-01-29 11: 28: 41Z
  1. çok yardımcı oldu !!!
    2017-04-06 07: 41: 02Z
  2. Bu sadece önemsiz bir ilişkidir
    2017-04-28 20: 17: 37Z

Numpy /scipy'e güvenmek yerine, cevabımın Pearson Korelasyon Katsayısı (PCC) hesaplamasında kodlamanın ve adımları anlamanın en kolay olması gerektiğini düşünüyorum.

 
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)

PCC’nin önemi temel olarak size iki değişkenin /listenin ne kadar güçlü bir şekilde ilişkilendirildiğini gösterir. PCC değerinin -1 ila 1 arasında değiştiğine dikkat etmek önemlidir. 0 ile 1 arasındaki bir değer pozitif bir korelasyonu gösterir. 0 değeri = en yüksek varyasyon (hiçbir korelasyon yok). -1 ile 0 arasındaki bir değer negatif bir korelasyonu gösterir.

    
12
2015-09-11 05: 49: 46Z
  1. Python'un yerleşik bir sum işlevi olduğunu unutmayın.
    2015-11-06 10: 27: 20Z
  2. 500+ değere sahip 2 listede şaşırtıcı bir karmaşıklığa ve yavaş performansa sahip.
    2016-02-07 13: 58: 31Z

Hmm, bu yanıtların birçoğunun kodu okuması uzun ve zor oldu ...

Dizilerle çalışırken şık olanı ile numpy 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
2013-10-31 15: 37: 53Z
  1. Bu cevabı çok sevmeme rağmen, fonksiyon içinde hem X hem de Y'yi kopyalamanızı /klonlamanızı öneririm. Aksi takdirde her ikisi de değişir, bu istenen bir davranış olmayabilir.
    2017-06-27 17: 56: 17Z

Bu, numpy kullanarak Pearson Correlation 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

    
6
2015-03-02 21: 13: 18Z

İşte mkh’in cevabında, kendisinden çok daha hızlı çalışan bir varyasyon ve numba kullanarak scipy.stats.pearsonr.

 
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
2015-03-22 13: 54: 52Z

Python'daki pandaları kullanarak Pearson katsayısı hesabı: Verileriniz listeler içerdiğinden bu yaklaşımı denemenizi tavsiye ederim. Veri yapınızı görselleştirip istediğiniz gibi güncelleyebildiğiniz için verilerinizle etkileşime girmek ve konsoldan değiştirmek çok kolay olacaktır. Ayrıca veri kümesini dışa aktarabilir, kaydedebilir ve daha sonra analiz için python konsolundan yeni veriler ekleyebilirsiniz. Bu kod daha basittir ve daha az kod satırı içerir. Verilerinizi daha ayrıntılı analiz için taramak için birkaç hızlı kod satırına ihtiyacınız olduğunu düşünüyorum.

Örnek:

 
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 

Ancak, veri kümesinin boyutunu veya analizden önce gerekli olabilecek dönüşümleri görmem için verilerinizi göndermediniz.

    
5
2018-09-09 18: 20: 06Z
  1. Merhaba, StackOverflow'a hoş geldiniz! Bu kodu neden seçtiğinize ve bu c’de nasıl uygulandığına dair kısa bir açıklama yapmayı deneyin.Cevabınızın başında ase!
    2018-09-09 15: 19: 53Z

İşte seyrek vektöre dayalı pearson korelasyonu için bir uygulama. Buradaki vektörler, (indeks, değer) olarak ifade edilen başlıkların bir listesi olarak ifade edilir. İki seyrek vektör farklı uzunluklarda olabilir, ancak tüm vektör boyutlarında aynı olmak zorundadır. Bu, birçok özelliğin kelime torbası olması nedeniyle vektör boyutunun son derece büyük olduğu metin madenciliği uygulamaları için faydalıdır ve bu nedenle hesaplamalar genellikle seyrek vektörler kullanılarak yapılır.

 
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
2013-09-15 20: 19: 24Z

Olasılığınızı belirli bir yönde (negatif veya pozitif korelasyon) bir korelasyon aramak bağlamında nasıl yorumlayabileceğinizi merak edebilirsiniz. İşte size bu konuda yardımcı olmak için yazdığım bir fonksiyon. Hatta doğru bile olabilir!

http://www.vassarstats.net/rsig.htmltopladığım bilgilere dayanıyor a> ve http://en.wikipedia.org/wiki/Student%27s_t_distribution , Burada yayınlanan diğer cevaplar için teşekkürler.

 
# 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
2013-01-09 02: 18: 32Z

Bu makaleye bir göz atabilirsiniz. Bu, geçmiş forex döviz çiftlerine dayanan korelasyonu hesaplamak için panda kütüphanesini (Python için) kullanan birden fazla dosyadan elde edilen verileri ve daha sonra seaborn kütüphanesini kullanarak bir ısı haritası grafiği oluşturmaya yönelik iyi belgelenmiş bir örnektir.

http://www.tradinggeeks.net/2015/08 /hesaplama korelasyon-in-piton /

    
1
2015-08-06 21: 00: 09Z

Bunun için çok basit ve anlaşılması kolay bir çözümüm var. Eşit uzunlukta iki dizi için, Pearson katsayısı aşağıdaki gibi kolayca hesaplanabilir:

 
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
    
1
2018-06-22 22: 21: 37Z
 
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
2017-12-20 11: 19: 36Z
  1. Yalnızca kod yanıtları iyi uygulama olarak kabul edilmez. Lütfen kodunuzun soruyu nasıl ele aldığını açıklamak için birkaç kelime eklemeyi düşünün. (SO'da bir soruyu nasıl yanıtlayacağınız konusunda yardım sayfasını okuyun)
    2017-12-20 11: 28: 55Z
kaynak yerleştirildi İşte