算法学习笔记----Day32(pandas进行股票数据和时间事件日志分析)
第一部分:股票数据分析
一.概述
例如一个股票数据的下载链接:
http://quotes.money.163.com/service/chddata.html?code=0600690&start=19931119&end=20180706&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;PCHG;TURNOVER;VOTURNOVER;VATURNOVER
把 code, start, end 字段修改一下即可下载其他股票在指定时间的交易数据。股票代码前面的那个数字表示的是交易所,0 表示上海证券交易所,1 表示深圳证券交易所。
二.数据分析
1.某数据的波动幅度:例如按月分析
adj_price = data['Adj Close']
resampled = adj_price.resample('m').ohlc()
(resampled.high - resampled.low) / resampled.low
2.增长曲线:adj_price.plot(figsize=(8, 6))
3.增长倍数:
1)最高增长倍数:total_max_growth = adj_price.max() / adj_price.min()
2)当前平均增长倍数:total_growth = adj_price.iloc[0] / adj_price.iloc[-1]
3)最大年均复合增长率:求出价格最高、最低的年份之差,再对增长倍数开相应次数的根号
min_date = adj_price.argmin()
max_date = adj_price.argmax()
max_growth_per_year = total_max_growth ** (1.0 / (max_date.year - min_date.year))
max_growth_per_year
4)平均年化增长率:
price_in_years = adj_price.to_period(freq='A').groupby(level=0).first() #按年分组并用每年第一月份数据表示
diff = price_in_years.diff() #求出每一年与上一年之差
rate_in_years = diff / (price_in_years - diff) #当年数据减去与上一年之差=上一年数据,差值/上年数据==增长率
rate_in_years.plot(kind='bar', figsize=(8,6)) #柱状图
X = [0, len(rate_in_years)]
Y = [0, 0]
plt.plot(X, Y, color='red', linestyle='-') #红色分割线,分割增长率正负
第二部分:时间事件日志
时间事件日志是统计个人时间的工具,使用特殊格式记录事件类别和花费的时间,如: “[探索发现] 体验 iMac 开发环境 [3h]”。
一.读取数据
%matplotlib inline
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.pylab import mpl
mpl.rcParams['font.sans-serif'] = ['Arial Unicode MS'] # 指定默认字体
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
#定义日期解析函数,只保留日期信息,不保留具体时、分、秒
def _date_parser(dstr):
return pd.Timestamp(dstr).date()
data = pd.read_csv('data/dida365.csv', header=3, index_col='Due Date', parse_dates=True, date_parser=_date_parser)
二.数据清洗
1.数据选择:
假定只关心己完成的事件,即 status != 0 的事件,且只需要List Name和Title字段:
df = data[data['Status'] != 0].loc[:, ['List Name', 'Title']]
2.数据解析(正则表达式):
对于“[编程] javascript exercism [1h]”的数据进行解析,得到事件类别和花费时间:
import re
#解析标签--类别
def parse_tag(value):
m = re.match(r'^(\[(.*?)\])?.*$', value)
if m and m.group(2):
return m.group(2)
else:
return '其他'
#解析花费时间
def parse_duration(value):
m = re.match(r'^.+?\[(.*?)([hm]?)\]$', value)
if m:
dur = 0
try:
dur = float(m.group(1))
except e:
print('parse duration error: \n%s' % e)
if m.group(2) == 'm':
dur = dur / 60.0
return dur
else:
return 0
titles = df['Title']
df['Tag'] = titles.map(parse_tag)
df['Duration'] = titles.map(parse_duration)
df.head()
三.数据分析
1.时间总览:平均每天投资在自己身上的时间=全部时间 / 总天数
df['Duration'].sum() / (end_date - start_date).days
2.精力分配:
tag_list = df.groupby('Tag').sum()
tag_list
tag_list['Duration'].plot.pie(figsize=(8, 8), fontsize=16, autopct='%1.2f')
3.专注力:
提取编程的数据,对日期进行重采样,然后转换成period时期,以月为周期,画出柱状图
programming = df[df['Tag'] == '编程']
programming.resample('m').sum().to_period(freq='m').plot.bar(figsize=(4, 4), fontsize=8)
4.动态精力分配:
1)对于日期作为索引的数据,首先用reset_index()和groupby将数据按照日期和行为(Tag)分组,然后用.pivot()进行轴向旋转,分组聚合后的日期作为行索引,Tag作为列索引,时间作为值:
#由于日期作为行索引有重复项,所以需要先重置索引然后进行分组聚合,将重复项合并
date_tags = df.reset_index().groupby(['Due Date', 'Tag']).sum()
#进行数据整理,用pivot()函数把日期作为行索引,Tag作为列索引,值为所花时间
dates = date_tags.reset_index().pivot(index='Due Date', columns='Tag', values='Duration')
#可以把开始到结束的时间补齐,未花费时间默认为NAN,用0填充
start_date = df.index.min().date()
end_date = df.index.max().date()
full_dates = dates.reindex(pd.date_range(start_date, end_date)).fillna(0)
full_dates.head()
2)按照月份重采样后绘图:
full_dates.resample('m').sum().to_period('m').plot.bar(stacked=True, figsize=(8, 8))
备注:
1.对于pandas中的DataFrame结构df,假定Status是某一个列索引的名称,则df[‘Status’] 等价于df.Status。
2.DataFrame的结构中,对于要使用.pivot()函数作为行索引的数据不能有重复数据,否则需要先进行分组聚合,然后reset_index()重置行索引,才可以轴向旋转。