Tôi đang tìm kiếm một hàm lấy hai danh sách đầu vào và trả về tương quan Pearson và tầm quan trọng của mối tương quan.
Tôi đang tìm kiếm một hàm lấy hai danh sách đầu vào và trả về tương quan Pearson và tầm quan trọng của mối tương quan.
Câu trả lời:
Bạn có thể xem qua 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
Mối tương quan Pearson có thể được tính toán với numpy corrcoef
.
import numpy
numpy.corrcoef(list1, list2)[0, 1]
Một thay thế có thể là một hàm scipy bản địa từ linregress tính toán:
độ dốc: độ dốc của đường hồi quy
đánh chặn: chặn đường hồi quy
giá trị r: hệ số tương quan
p-value: giá trị p hai mặt cho một bài kiểm tra giả thuyết có giả thuyết null là độ dốc bằng không
stderr: Lỗi tiêu chuẩn của dự toán
Và đây là một ví dụ:
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)
sẽ trả lại cho bạn:
LinregressResult(slope=0.20833333333333337, intercept=13.375, rvalue=0.14499815458068521, pvalue=0.68940144811669501, stderr=0.50261704627083648)
lineregress(two_row_df)
Nếu bạn không muốn cài đặt scipy, tôi đã sử dụng bản hack nhanh này, được sửa đổi một chút từ Lập trình thông minh lập trình :
(Đã chỉnh sửa cho chính xác.)
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'
lúcnum = psum - (sum_x * sum_y/n)
Các mã sau đây là một giải thích thẳng của định nghĩa :
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)
Kiểm tra:
print pearson_def([1,2,3], [1,5,7])
trả lại
0.981980506062
Điều này đồng ý với Excel, máy tính này , SciPy (cũng là NumPy ), lần lượt trả về 0,981980506 và 0,9819805060619657 và 0,98198050606196574.
R :
> cor( c(1,2,3), c(1,5,7))
[1] 0.9819805
EDIT : Đã sửa lỗi được chỉ ra bởi một người bình luận.
sum(x) / len(x)
bạn chia ints, không nổi. Vì vậy sum([1,5,7]) / len([1,5,7]) = 13 / 3 = 4
, theo phân chia số nguyên (trong khi bạn muốn 13. / 3. = 4.33...
). Để sửa nó, hãy viết lại dòng này dưới dạng float(sum(x)) / float(len(x))
(một float là đủ, vì Python tự động chuyển đổi nó).
Bạn cũng có thể làm điều này với 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()
Điều này mang lại
0 1 2
0 1.000000 0.745601 0.916579
1 0.745601 1.000000 0.544248
2 0.916579 0.544248 1.000000
Thay vì dựa vào numpy / scipy, tôi nghĩ rằng câu trả lời của tôi nên dễ viết mã nhất và hiểu các bước trong tính toán Hệ số tương quan Pearson (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)
Tầm quan trọng của PCC về cơ bản là cho bạn thấy mức độ tương quan mạnh mẽ của hai biến / danh sách. Điều quan trọng cần lưu ý là giá trị PCC nằm trong khoảng từ -1 đến 1 . Giá trị từ 0 đến 1 biểu thị mối tương quan dương. Giá trị 0 = biến thiên cao nhất (không có tương quan gì). Giá trị từ -1 đến 0 biểu thị mối tương quan âm.
sum
hàm dựng sẵn .
Tính toán hệ số Pearson bằng cách sử dụng gấu trúc trong trăn: Tôi khuyên bạn nên thử phương pháp này vì dữ liệu của bạn chứa danh sách. Sẽ dễ dàng tương tác với dữ liệu của bạn và thao tác dữ liệu từ bảng điều khiển vì bạn có thể hình dung cấu trúc dữ liệu của mình và cập nhật dữ liệu theo ý muốn. Bạn cũng có thể xuất tập dữ liệu và lưu nó và thêm dữ liệu mới từ bảng điều khiển python để phân tích sau. Mã này đơn giản hơn và chứa ít dòng mã hơn. Tôi giả sử bạn cần một vài dòng mã nhanh để sàng lọc dữ liệu của mình để phân tích thêm
Thí dụ:
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
Tuy nhiên, bạn đã không đăng dữ liệu của bạn cho tôi để xem kích thước của tập dữ liệu hoặc các biến đổi có thể cần thiết trước khi phân tích.
Hmm, nhiều phản hồi trong số này có mã dài và khó đọc ...
Tôi khuyên bạn nên sử dụng numpy với các tính năng tiện lợi của nó khi làm việc với mảng:
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)
Đây là một triển khai của hàm Pearson Correlation bằng cách sử dụng 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
Đây là một biến thể của câu trả lời của mkh chạy nhanh hơn nó rất nhiều và scipy.stats.pearsonr, sử dụng 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)
Đây là một triển khai cho tương quan pearson dựa trên vector thưa thớt. Các vectơ ở đây được thể hiện dưới dạng một danh sách các bộ dữ liệu được biểu thị dưới dạng (chỉ mục, giá trị). Hai vectơ thưa thớt có thể có chiều dài khác nhau nhưng trên tất cả kích thước vectơ sẽ phải giống nhau. Điều này hữu ích cho các ứng dụng khai thác văn bản trong đó kích thước vectơ cực kỳ lớn do hầu hết các tính năng là túi từ và do đó các phép tính thường được thực hiện bằng cách sử dụng các vectơ thưa thớt.
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)
Bài kiểm tra đơn vị:
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)
Tôi có một giải pháp rất đơn giản và dễ hiểu cho việc này. Đối với hai mảng có độ dài bằng nhau, hệ số Pearson có thể được tính toán dễ dàng như sau:
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
Bạn có thể tự hỏi làm thế nào để giải thích xác suất của bạn trong bối cảnh tìm kiếm một mối tương quan theo một hướng cụ thể (tương quan tiêu cực hoặc tích cực.) Đây là một chức năng tôi đã viết để giúp với điều đó. Nó thậm chí có thể đúng!
Nó dựa trên thông tin tôi lượm lặt được từ http://www.vassarstats.net/rsig.html và http://en.wikipedia.org/wiki/Student%27s_t_distribution , nhờ các câu trả lời khác được đăng ở đây.
# 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)
Bạn có thể xem bài viết này. Đây là một ví dụ được chứng minh bằng tài liệu để tính toán tương quan dựa trên dữ liệu cặp tiền tệ ngoại hối lịch sử từ nhiều tệp bằng thư viện gấu trúc (đối với Python), sau đó tạo một sơ đồ nhiệt bằng thư viện seaborn.
http://www.tradinggeek.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