利用Python计算Spearman相关系数
自己编程实现Spearman相关系数的计算。
Spearman相关系数
Spearman相关系数是一种秩相关系数。数据的秩简单来说就是该样本数据的次序统计量。秩统计量是基于样本值的 大小在全体样本中所占位次(秩)的统计量
例:有样本数据-0.8, -3.1, 1.1, -5.2, 4.2,次序统计量的值是-5.2, -3.1, -0.8, 1.1, 4.2,则秩统计量的取值是3,2,4,1,5。
若观测数据中两个值相等,则秩取为它们应排序位置的平均值。
例:有样本数据-0.8,, -3.1, -0.8,秩为2.5, 1, 2.5。
其中 ,Ri是X的秩统计量,Si是Y的秩统计量,Spearman相关系数定义为这两组秩统计量的相关系数。
拆解任务
- 读入数据
- 排序
- 第一次计算秩统计量
- 查找是否有相等数据,纠正次序统计量
- 计算Spearman相关系数
排序
array形式
da2 = pd.read_excel(fb,header = None)
da3 = da2.values #将pd格式转换成数组
row = da2.shape[0]
col = da2.shape[1]
sa1 = np.sort(da3[:,0]) #数据排序
sa2 = np.sort(da3[:,1])
sb1 = da3[:,0]
sb2 = da3[:,1]
pr = np.ones((1,row))
ps = np.ones((1,row))
list形式
wb = xlrd.open_workbook(r'C:\Users\LENOVO\Documents\Tencent Files\973391860\FileRecv\eg1d9data.xls')#打开文件
sheet1 = wb.sheet_by_index(0)#通过索引获取表格
x1 = sheet1.col_values(0)
x2 = sheet1.col_values(0) #不可直接x2=x1,这样会变成创建副本,x2跟着x1变
y1 = sheet1.col_values(1)
y2 = sheet1.col_values(1) #获取列内容
n = len(x1)
x1.sort() #排序
y1.sort()
pr = np.ones((1,n))
ps = np.ones((1,n))
不可直接x2=x1,这样会变成创建副本,x2跟着x1变
第一次计算秩统计量
array形式
for i in range(row):
[c]=np.where(sa1==sb1[i])
[d] = np.where(sa2==sb2[i]) #确定元素位置
pr[0][i] = c[0]
ps[0][i] = d[0]
np.where返回的是元组形式,要获取元组数据,应用[]来获取
list形式
for i in range(n):
sx = sx + np.square(x2[i] - mx)
sy = sy + np.square(y2[i] - my)
sz = sz + (x2[i]-mx)*(y2[i]-my)
pr[0][i] = x1.index(x2[i]) #获取秩统计量,此处因数据为列表形式,故用此方法,数组另有方法
ps[0][i] = y1.index(y2[i]) #列表对于重复元素,只能获取第一个出现元素的索引,而数组可以一次获取,但数组获取返回的是元组形式
纠正次序统计量
array形式
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr): #处理重复元素的秩统计量
[a] = np.where(x1==repeat[j])
m = rcount[j]
b = sum(a)/m
for k in range(m):
[d,c] = np.where(z==a[k])
z[0][c] = b
list形式
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr): #处理重复元素的秩统计量
a = x1.index(repeat[j])
m = rcount[j]
b = (m*a+(m-1)*m/2)/m
[d,c] = np.where(z==a)
z[0][c] = b
计算Spearman相关系数
这里array和list的代码没有区别。 array形式
findrank(sa1,pr)
findrank(sa2,ps)
qxy = 0
for i in range(row):
qxy = qxy + np.square(pr[0][i] - ps[0][i]) #计算spearman
qxy = 1 - 6/row/(np.square(row)-1)*qxy
print(qxy)
list形式
findrank(x1,pr)
findrank(y1,ps)
qxy = 0
for i in range(n):
qxy = qxy + np.square(pr[0][i] - ps[0][i]) #计算spearman
qxy = 1 - 6/n/(np.square(n)-1)*qxy
完整代码
array形式
##数组形式
fb = r'C:\Users\LENOVO\Documents\Tencent Files\973391860\FileRecv\eg1d9data.xls'
da2 = pd.read_excel(fb,header = None)
da3 = da2.values
row = da2.shape[0]
col = da2.shape[1]
sa1 = np.sort(da3[:,0])
sa2 = np.sort(da3[:,1])
sb1 = da3[:,0]
sb2 = da3[:,1] # 排序
pr = np.ones((1,row))
ps = np.ones((1,row))
for i in range(row):
[c]=np.where(sa1==sb1[i])
[d] = np.where(sa2==sb2[i]) #第一次计算秩统计量
pr[0][i] = c[0]
ps[0][i] = d[0]
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr): #处理重复元素的秩统计量
[a] = np.where(x1==repeat[j])
m = rcount[j]
b = sum(a)/m
for k in range(m):
[d,c] = np.where(z==a[k])
z[0][c] = b
findrank(sa1,pr)
findrank(sa2,ps)
qxy = 0
for i in range(row):
qxy = qxy + np.square(pr[0][i] - ps[0][i]) #计算spearman
qxy = 1 - 6/row/(np.square(row)-1)*qxy
print(qxy)
list形式
wb = xlrd.open_workbook(r'C:\Users\LENOVO\Documents\Tencent Files\973391860\FileRecv\eg1d9data.xls')#打开文件
sheet1 = wb.sheet_by_index(0)#通过索引获取表格
x1 = sheet1.col_values(0)
x2 = sheet1.col_values(0) #不可直接x2=x1,这样会变成创建副本,x2跟着x1变
y1 = sheet1.col_values(1)
y2 = sheet1.col_values(1)#获取列内容
n = len(x1)
x1.sort() #排序
y1.sort()
pr = np.ones((1,n))
ps = np.ones((1,n))
for i in range(n):
sx = sx + np.square(x2[i] - mx)
sy = sy + np.square(y2[i] - my)
sz = sz + (x2[i]-mx)*(y2[i]-my)
pr[0][i] = x1.index(x2[i]) #获取秩统计量,此处因数据为列表形式,故用此方法,数组另有方法
ps[0][i] = y1.index(y2[i]) #列表对于重复元素,只能获取第一个出现元素的索引,而数组可以一次获取,但数组获取返回的是元组形式
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr): #处理重复元素的秩统计量
a = x1.index(repeat[j])
m = rcount[j]
b = (m*a+(m-1)*m/2)/m
[d,c] = np.where(z==a)
z[0][c] = b
findrank(x1,pr)
findrank(y1,ps)
qxy = 0
for i in range(n):
qxy = qxy + np.square(pr[0][i] - ps[0][i]) #计算spearman
qxy = 1 - 6/n/(np.square(n)-1)*qxy
计算Spearman矩阵
array形式
##数组形式
fb = r'C:\Users\LENOVO\Documents\Tencent Files\973391860\FileRecv\eg1d10data.xls'
da2 = pd.read_excel(fb,header = None)
da3 = da2.values
row = da2.shape[0]
col = da2.shape[1]
q = np.ones((col,col))
for i in range(col):
for j in range(col):
sa1 = np.sort(da3[:,i])
sa2 = np.sort(da3[:,j])
sb1 = da3[:,i]
sb2 = da3[:,j]
pr = np.ones((1,row))
ps = np.ones((1,row))
for k in range(row):
[c]=np.where(sa1==sb1[k])
[d] = np.where(sa2==sb2[k])
pr[0][k] = c[0]
ps[0][k] = d[0]
findrank(sa1,pr)
findrank(sa2,ps)
qxy = 0
for p in range(row):
qxy = qxy + np.square(pr[0][p] - ps[0][p]) #计算spearman
q[i][j] = 1 - 6/row/(np.square(row)-1)*qxy
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr): #处理重复元素的秩统计量
[a] = np.where(x1==repeat[j])
m = rcount[j]
b = sum(a)/m
for k in range(m):
[d,c] = np.where(z==a[k])
z[0][c] = b
print(q)
list形式
fb = r'C:\Users\LENOVO\Documents\Tencent Files\973391860\FileRecv\eg1d10data.xls'
da2 = pd.read_excel(fb,header = None)
da3 = da2.values
row = da2.shape[0]
col = da2.shape[1]
def findrank(x1,z):
repeat =[item for item, count in Counter(x1).items() if count > 1] # 找重复元素
rcount = [count for item, count in Counter(x1).items() if count > 1] #找重复次数
nr = len(repeat)
for j in range(nr):
a = x1.index(repeat[j])
m = rcount[j]
b = (m*a+(m-1)*m/2)/m
[d,c] = np.where(z==a)
z[0][c] = b
def getqxy(x1,pr,y1,ps):
findrank(x1,pr)
findrank(y1,ps)
qxy = 0
for i in range(row):
qxy = qxy + np.square(pr[0][i] - ps[0][i])
qxy = 1 - 6/n/(np.square(row)-1)*qxy
return qxy
pr = np.ones((1,row))
ps = np.ones((1,row))
q = np.ones((col,col))
for i in range(col):
for j in range(col):
sa1 = da3[:,i].tolist()
sa2 = da3[:,j].tolist()
sb1 = da3[:,i].tolist()
sb2 = da3[:,j].tolist()
sa1.sort()
sa2.sort()
for k in range(row):
pr[0][k] = sa1.index(sb1[k]) #获取秩统计量
ps[0][k] = sa2.index(sb2[k])
q[i][j] = getqxy(sa1,pr,sa2,ps)
print('my spearman:\n',q)