前置:
文章中用到的数据
链接:https://pan.baidu.com/s/1rKLM45dq_xIKxcI54Nq0qg
提取码:c298
概念:
最终效果图:
计算过程(jupyter notebook):
import matplotlib.pyplot as plt
import pylab as pl
import pandas as pd
import math
df = pd.read_csv('./temptemp.csv',encoding='utf-8')
df['o_date'] = df['date']
df['o_date'] = pd.to_datetime(df['o_date'])
df.sort_values(by='o_date', ascending=True, inplace=True)
df['count'] = range(len(df)) # 用于标记x轴的位置
df.head()
res_list = []
temp_hv = None # 此前最大值
temp_hv_date = None # 此前最大值对应的日期
temp_hv_loc = None # 此前最大值对应的位置
temp_duration = None # 当再次到达此前最大值时经过的天数
for i,row in df.iterrows():
if temp_hv is None:
temp_hv = row['value']
temp_hv_date = row['date']
temp_hv_loc = row['count']
temp_duration = 0
else:
if row['value'] >= temp_hv:
# 数值回到此前最高点,一个挫跌期结束,记录
res_list.append([temp_hv_loc,temp_hv_date,temp_hv,row['count'],row['date'],row['value'],temp_duration])
temp_hv = row['value']
temp_hv_date = row['date']
temp_hv_loc = row['count']
temp_duration = 0
pass
else:
temp_duration += 1
temp_max = None # 放置最大挫跌期天数
temp_max_obj = None # 放置最大挫跌期
for item in res_list:
if item[-1]<=0:
continue
if temp_max is None:
temp_max = item[-1]
temp_max_obj = item
else:
if item[-1]>temp_max:
temp_max = item[-1]
temp_max_obj = item
# 绘制折线图,标记最大挫跌区域
def draw_trend_and_withdraw(xs,ys,title,res_points):
plt.figure(figsize=(20,10))
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
xs00 = range(len(xs))
plt.plot(xs00,ys)
# 只显示10个x轴刻度
xs00_=[]
xs_ =[]
for i in range(0,len(xs),math.floor(len(xs)/10)):
xs00_.append(i)
xs_.append(xs[i])
plt.xticks(xs00_,xs_,rotation=30)
plt.title(title)
for item in res_points:
min_x = item['min_x']
min_y = item['min_y']
max_x = item['max_x']
max_y = item['max_y']
show_min_str = item['show_min_str']
show_max_str = item['show_max_str']
withdraw = item['withdraw']
plt.scatter(min_x, min_y, color='r') # 标记最低点
plt.scatter(max_x, max_y, color='r') # 标记最高点
plt.annotate(show_min_str, xytext=(min_x, min_y), xy=(min_x, min_y)) # 标记提示
plt.annotate(show_max_str, xytext=(max_x, max_y), xy=(max_x, max_y)) # 标记提示
plt.plot([min_x, max_x], [min_y, max_y], color='b', linestyle='--') # 连接最低点和最高点
plt.annotate(withdraw, xytext=((max_x + min_x) / 2, (max_y + min_y) / 2), xy=((max_x + min_x) / 2, (max_y + min_y) / 2)) # 标记提示
pass
plt.show()
绘制折线图
temp_res_list = [{
'min_x':temp_max_obj[0],
'min_y':temp_max_obj[2],
'max_x':temp_max_obj[3],
'max_y':temp_max_obj[5],
'show_min_str':temp_max_obj[1],
'show_max_str':temp_max_obj[4],
'withdraw':str(temp_max_obj[-1])+'天'
}]
xs = df['date'].values.tolist()
ys = df['value'].values.tolist()
title_str = '最大挫跌期'
draw_trend_and_withdraw(xs,ys,title_str,temp_res_list)