判断一组数据的变化趋势:斜率法和cox_stuart趋势检验

斜率法

'''
1.做最小二乘拟合,把序列拟合成一条直线;
2.根据直线的斜率k可以得知序列的主要走势:
例如:(1)k > 0.1763 上升  (2) k < -0.1763 下降 (3)其他
3.然后计算序列各点到直线的距离(和方差一样)
设定一个阈值L,统计超过L的点数目,点数目越多说明序列震荡越厉害
'''
import numpy as np
import math
def trendline(data):  # 拟合曲线
  order=1
  index=[i for i in range(1,len(data)+1)] # x轴坐标
  coeffs = np.polyfit(index, list(data), order) # 曲线拟合
  # k = coeffs[0] # 斜率
  return coeffs

def judge_slope(coeffs, data, degree, shake=1):
  tan_k = math.tan(degree*math.pi/180)	# 注意弧度转化
  # print(coeffs[0])
  # print(tan_k)
  if coeffs[0] >= tan_k:
    return "上升"
  elif coeffs[0] <= -tan_k:
    return "下降"
  else:
    return get_shake(coeffs, data, shake)

def get_shake(coeffs, data, shake):
  count = 0
  for i, d in enumerate(data): # i+1相当于横坐标,从1开始
    y = np.polyval(coeffs, i+1)
    count += (y-d)**2
  # print("count: ",count)
  if count > shake:
    return "波动"
  else:
    return "平稳"

if __name__ == '__main__':
  data = [10,15,29,30,56,45,41,19,37,48,46]
  coeffs = trendline(data)

  res = judge_slope(coeffs, data, degree=1, shake=1)
  print(res)

cox_stuart趋势检验

'''
判断一组数据的趋势是上升还是下降
'''
import scipy.stats as stats
def cox_stuart(list_c,debug=False):
	lst=list_c.copy()
	raw_len=len(lst)
	if raw_len%2==1:
		del lst[int((raw_len-1)/2)]    # 删除中位数
	c=int(len(lst)/2)
	n_pos=n_neg=0
	for i in range(c):
		diff=lst[i+c]-lst[i]
		if diff>0:
			n_pos+=1
		elif diff<0:
			n_neg+=1
		else:
			continue
	num=n_pos+n_neg
	k=min(n_pos,n_neg)           #  双边检验
	print("k: ",k)
	print("num:",num)
	p_value=2*stats.binom.cdf(k,num,0.5)  #  二项分布
	if debug:
		print('fall:%i, rise:%i, p-value:%f'%(n_neg, n_pos, p_value))
	if n_pos>n_neg and p_value<0.05:   #  双边检验
		return 'increasing'
	elif n_neg>n_pos and p_value<0.05:  #  双边检验
		return 'decreasing'
	else:
		return 'no trend'

list_c = [10,15,29,30,56,45,41,19,37,48,46]	# 数据量太小,得不到有效结果
res = cos_staut(list_c, True)
print(res)

参考链接
https://wenku.baidu.com/view/cec731b981c758f5f61f6760.html
https://zhuanlan.zhihu.com/p/112703276
https://bbs.csdn.net/topics/350253275
https://blog.csdn.net/speargod/article/details/79939798

猜你喜欢

转载自blog.csdn.net/tailonh/article/details/113887752