Ben girdi iki liste olarak alır ve Pearson korelasyon ve korelasyonun önemini döndüren bir işlev arıyorum .
Ben girdi iki liste olarak alır ve Pearson korelasyon ve korelasyonun önemini döndüren bir işlev arıyorum .
Yanıtlar:
Şuna bir göz atabilirsiniz 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
Pearson korelasyonu numpy ile hesaplanabilir corrcoef
.
import numpy
numpy.corrcoef(list1, list2)[0, 1]
Bir alternatif, linregress'ten yerel bir scipy fonksiyonu olabilir ve bu da aşağıdakileri hesaplar:
eğim: regresyon çizgisinin eğimi
kesme noktası: regresyon çizgisinin kesilmesi
r-değeri: korelasyon katsayısı
p değeri: sıfır hipotezi eğimin sıfır olduğu 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 dönecektir:
LinregressResult(slope=0.20833333333333337, intercept=13.375, rvalue=0.14499815458068521, pvalue=0.68940144811669501, stderr=0.50261704627083648)
lineregress(two_row_df)
Scipy kurmak istemiyorsanız, Programlı Kolektif Zeka'dan biraz değiştirilmiş bu hızlı hack'i kullandım :
(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
TypeError: unsupported operand type(s) for -: 'itertools.imap' and 'float'
atnum = psum - (sum_x * sum_y/n)
Aşağıdaki kod, tanımın düz 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)
Ölçek:
print pearson_def([1,2,3], [1,5,7])
İadeler
0.981980506062
Bu Excel ile aynı görüşü bu hesap makinesi , SciPy (ayrıca NumPy sırasıyla 0.981980506 ve 0.9819805060619657 ve 0.98198050606196574, dönüş).
R :
> cor( c(1,2,3), c(1,5,7))
[1] 0.9819805
EDIT : Bir yorumcunun işaret ettiği bir hata düzeltildi.
sum(x) / len(x)
ints bölmek, yüzen değil. Yani sum([1,5,7]) / len([1,5,7]) = 13 / 3 = 4
, tamsayıya göre (istediğiniz gibi 13. / 3. = 4.33...
). Düzeltmek için bu satırı yeniden yazın float(sum(x)) / float(len(x))
(bir şamandıra yeterlidir, çünkü Python otomatik olarak dönüştürür).
Bunu aşağıdakilerle de yapabilirsiniz pandas.DataFrame.corr
:
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
Numpy / scipy'e güvenmek yerine, cevabımın Pearson Korelasyon Katsayısı'nı (PCC) hesaplama adımlarını kodlamak ve anlamak için 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)
Önemi PCC nasıl size göstermek için temelde güçlü bir korelasyon iki değişken / listelerdir. PCC değerinin -1 ile 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 (herhangi bir korelasyon yoktur). -1 ile 0 arasındaki bir değer negatif bir korelasyona işaret eder.
sum
işlevi olduğunu unutmayın .
Python'da pandalar kullanarak Pearson katsayısı hesaplaması: Verileriniz listeler içerdiğinden bu yaklaşımı denemenizi öneririm. Veri yapınızı görselleştirip istediğiniz gibi güncelleyebileceğinizden verilerinizle etkileşim kurmak ve konsoldan değiştirmek kolay olacaktır. Ayrıca veri kümesini dışa aktarabilir ve kaydedebilir ve daha sonra analiz etmek için python konsolundan yeni veriler ekleyebilirsiniz. Bu kod daha basittir ve daha az kod satırı içerir. Daha fazla analiz için verilerinizi taramak için birkaç hızlı kod satırına ihtiyacınız olduğunu varsayıyorum
Misal:
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örmek için verilerinizi bana göndermediniz.
Hmm, bu yanıtların çoğunun kodu uzun ve zor okunuyor ...
Dizilerle çalışırken nifty özellikleriyle 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)
Bu numpy kullanarak Pearson Korelasyon fonksiyonunun 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
İşte mkh cevabından ondan çok daha hızlı çalışan bir değişken ve scipy.stats.pearsonr, numba kullanarak.
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)
İşte seyrek vektöre dayalı pearson korelasyonu için bir uygulama. Buradaki vektörler, (indeks, değer) olarak ifade edilen tupleslerin bir listesi olarak ifade edilir. İki seyrek vektör farklı uzunlukta olabilir, ancak tüm vektör boyutlarının aynı olması gerekir. Bu, çoğu özelliğin kelime torbası olması nedeniyle vektör boyutunun çok büyük olduğu metin madenciliği uygulamaları için yararlıdır ve bu nedenle 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)
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
Olasılığınızı belirli bir yönde bir korelasyon arama bağlamında nasıl yorumlayacağınızı merak edebilirsiniz (negatif veya pozitif korelasyon.) İşte size yardımcı olmak için yazdığım bir fonksiyon. Doğru bile olabilir!
Burada yayınlanan diğer yanıtlar sayesinde http://www.vassarstats.net/rsig.html ve http://en.wikipedia.org/wiki/Student%27s_t_distribution'dan topladığım bilgilere dayanmaktadır .
# 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)
Bu makaleye göz atabilirsiniz. Bu, panda kütüphanesini (Python için) kullanarak birden çok dosyadan geçmiş forex döviz çiftleri verilerine dayanan korelasyonu hesaplamak ve daha sonra deniz dibinin kütüphanesini kullanarak bir ısı haritası çizimi oluşturmak için iyi belgelenmiş bir örnektir.
http://www.tradinggeeks.net/2015/08/calculating-correlation-in-python/
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