ฉันกำลังมองหาฟังก์ชั่นที่รับเป็นรายการสองรายการและคืนค่าความสัมพันธ์ของเพียร์สันและความสำคัญของความสัมพันธ์
ฉันกำลังมองหาฟังก์ชั่นที่รับเป็นรายการสองรายการและคืนค่าความสัมพันธ์ของเพียร์สันและความสำคัญของความสัมพันธ์
คำตอบ:
คุณสามารถดู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
ความสัมพันธ์เพียร์สันสามารถคำนวณกับ corrcoef
numpy
import numpy
numpy.corrcoef(list1, list2)[0, 1]
ทางเลือกสามารถเป็นฟังก์ชัน scipy ดั้งเดิมจากlinregressซึ่งคำนวณ:
ความชัน: ความชันของเส้นถดถอย
สกัดกั้น: สกัดกั้นของสายการถดถอย
r-value: สัมประสิทธิ์สหสัมพันธ์
p-value: p-value สองด้านสำหรับการทดสอบสมมติฐานที่มีสมมติฐานว่างคือความชันเป็นศูนย์
stderr: ข้อผิดพลาดมาตรฐานของการประมาณ
และนี่คือตัวอย่าง:
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)
จะกลับมาคุณ:
LinregressResult(slope=0.20833333333333337, intercept=13.375, rvalue=0.14499815458068521, pvalue=0.68940144811669501, stderr=0.50261704627083648)
lineregress(two_row_df)
หากคุณไม่รู้สึกว่าต้องการติดตั้ง scipy ฉันใช้แฮ็คด่วนนี้ปรับเปลี่ยนเล็กน้อยจากProgramming Collective Intelligence :
(แก้ไขเพื่อความถูกต้อง)
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)
รหัสต่อไปนี้เป็นการตีความคำจำกัดความแบบตรงขึ้น:
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)
ทดสอบ:
print pearson_def([1,2,3], [1,5,7])
ผลตอบแทน
0.981980506062
นี้เห็นด้วยกับ Excel, เครื่องคิดเลขนี้ , SciPy (ยังNumPy ) ซึ่งกลับ 0.981980506 และ 0.9819805060619657 และ .98198050606196574 ตามลำดับ
R :
> cor( c(1,2,3), c(1,5,7))
[1] 0.9819805
แก้ไข : แก้ไขข้อผิดพลาดที่ชี้ให้เห็นโดยผู้แสดงความคิดเห็น
sum(x) / len(x)
คุณแบ่ง ints ไม่ลอย ดังนั้นsum([1,5,7]) / len([1,5,7]) = 13 / 3 = 4
ตามหารจำนวนเต็ม (ในขณะที่คุณต้องการ13. / 3. = 4.33...
) หากต้องการแก้ไขให้เขียนบรรทัดนี้ใหม่เป็นfloat(sum(x)) / float(len(x))
(หนึ่งโฟลพอเพียงเป็นงูหลามแปลงมันโดยอัตโนมัติ)
คุณสามารถทำได้ด้วย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()
สิ่งนี้จะช่วยให้
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 ฉันคิดว่าคำตอบของฉันควรเป็นรหัสที่ง่ายที่สุดและเข้าใจขั้นตอนในการคำนวณสัมประสิทธิ์สหสัมพันธ์เพียร์สัน (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)
ความสำคัญของ PCC นั้นโดยทั่วไปจะแสดงให้คุณเห็นว่ามีความสัมพันธ์อย่างมากกับตัวแปร / รายการสองรายการ มันเป็นสิ่งสำคัญที่จะต้องทราบว่าค่า PCC ช่วงจาก -1 ถึง 1 ค่าระหว่าง 0 ถึง 1 หมายถึงความสัมพันธ์เชิงบวก ค่า 0 = ความแปรปรวนสูงสุด (ไม่มีความสัมพันธ์ใด ๆ ) ค่าระหว่าง -1 ถึง 0 หมายถึงความสัมพันธ์เชิงลบ
sum
ฟังก์ชั่นในตัว
การคำนวณสัมประสิทธิ์เพียร์สันโดยใช้แพนด้าในไพ ธ อน: ฉันขอแนะนำให้ลองวิธีนี้เนื่องจากข้อมูลของคุณมีรายการ มันจะง่ายต่อการโต้ตอบกับข้อมูลของคุณและจัดการมันจากคอนโซลเนื่องจากคุณสามารถเห็นโครงสร้างข้อมูลของคุณและปรับปรุงตามที่คุณต้องการ คุณยังสามารถส่งออกชุดข้อมูลและบันทึกและเพิ่มข้อมูลใหม่จากคอนโซลหลามสำหรับการวิเคราะห์ในภายหลัง รหัสนี้ง่ายกว่าและมีรหัสน้อยกว่า ฉันสมมติว่าคุณต้องการโค้ดสั้น ๆ สองสามบรรทัดเพื่อคัดกรองข้อมูลของคุณเพื่อการวิเคราะห์เพิ่มเติม
ตัวอย่าง:
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
อย่างไรก็ตามคุณไม่ได้โพสต์ข้อมูลเพื่อให้ฉันเห็นขนาดของชุดข้อมูลหรือการแปลงที่อาจจำเป็นก่อนการวิเคราะห์
อืมคำตอบเหล่านี้ส่วนใหญ่ยาวและอ่านยาก ...
ฉันขอแนะนำให้ใช้ numpy กับคุณสมบัติที่ดีเมื่อทำงานกับอาร์เรย์:
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)
นี่คือการใช้งานของ Pearson Correlation function โดยใช้ 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
นี่คือตัวแปรของคำตอบของ mkh ที่ทำงานได้เร็วกว่าและ scipy.stats.pearsonr ใช้ 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)
นี่คือการดำเนินการสำหรับความสัมพันธ์ของเพียร์สันตามเวกเตอร์กระจัดกระจาย เวกเตอร์ที่นี่จะแสดงเป็นรายการของสิ่งอันดับที่แสดงเป็น (ดัชนีค่า) เวกเตอร์ที่กระจัดกระจายสองตัวอาจมีความยาวต่างกัน แต่สำหรับขนาดเวกเตอร์ทั้งหมดจะต้องเท่ากัน สิ่งนี้มีประโยชน์สำหรับแอปพลิเคชันการทำเหมืองข้อความที่ขนาดเวกเตอร์มีขนาดใหญ่มากเนื่องจากคุณสมบัติส่วนใหญ่เป็นถุงคำและการคำนวณจึงมักจะใช้เวกเตอร์แบบกระจาย
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)
การทดสอบหน่วย:
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)
ฉันมีทางออกที่ง่ายและเข้าใจง่ายสำหรับเรื่องนี้ สำหรับสองอาร์เรย์ที่มีความยาวเท่ากันสัมประสิทธิ์ Pearson สามารถคำนวณได้ง่ายดังนี้
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
คุณอาจสงสัยว่าจะตีความความน่าจะเป็นของคุณอย่างไรในบริบทของการมองหาความสัมพันธ์ในทิศทางใดทิศทางหนึ่ง (ความสัมพันธ์เชิงลบหรือบวก) นี่คือฟังก์ชันที่ฉันเขียนเพื่อช่วยในเรื่องนั้น มันอาจจะถูกต้อง!
มันขึ้นอยู่กับข้อมูลที่รวบรวมจากhttp://www.vassarstats.net/rsig.htmlและhttp://en.wikipedia.org/wiki/Student%27s_t_distribution% 27sขอบคุณคำตอบอื่น ๆ ที่โพสต์ไว้ที่นี่
# 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)
คุณสามารถดูที่บทความนี้ นี่เป็นตัวอย่างที่มีการบันทึกไว้อย่างดีสำหรับการคำนวณความสัมพันธ์ตามข้อมูลคู่สกุลเงิน forex ในอดีตจากหลายไฟล์โดยใช้ห้องสมุดแพนด้า (สำหรับ Python) จากนั้นสร้างพล็อต Heatmap โดยใช้ห้องสมุดซีบอร์น
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