Python数据科学包(六)—–数据可视化和例子

756-周同学

发表文章数:47

热门标签

, , ,
首页 » 数据科学库 » 正文

一. 数据可视化

Pandas 的数据可视化使用 matplotlib 为基础组件。更基础的信息可参阅 matplotlib 相关内容。本节主要介绍 Pandas 里提供的比 matplotlib 更便捷的数据可视化操作。

1. 线型图

Series 和 DataFrame 都提供了一个 plot 的函数。可以直接画出线形图。

ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.describe()
ts.plot()
# ts.plot? for more help
ts.plot(title='cumsum', style='r-', ylim=[-30, 30], figsize=(4, 3));
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=list('ABCD'))
df = df.cumsum()
df.describe()
# df.plot? for more help
df.plot(title='DataFrame cumsum', figsize=(4, 12), subplots=True, sharex=True, sharey=True);
df['I'] = np.arange(len(df))
df.plot(x='I', y=['A', 'C'])

2. 柱状图

df = pd.DataFrame(np.random.rand(10, 4), columns=['A', 'B', 'C', 'D'])
df.ix[1].plot(kind='bar')
df.plot.barh(stacked=True)

3. 直方图

直方图是一种对值频率进行离散化的柱状图。数据点被分到离散的,间隔均匀的区间中,绘制各个区间中数据点的数据。

df = pd.DataFrame({'a': np.random.randn(1000) + 1, 'b': np.random.randn(1000),
                   'c': np.random.randn(1000) - 1}, columns=['a', 'b', 'c'])
df['a'].plot.hist(bins=10)
df.plot.hist(subplots=True, sharex=True, sharey=True)
df.plot.hist(alpha=0.5)
df.plot.hist(stacked=True, bins=20, grid=True)

4. 密度图

正态分布(高斯分布)就是一种自然界中广泛存在密度图。比如我们的身高,我们的财富,我们的智商都符合高斯分布。

df['a'].plot.kde()
df.plot.kde()
df.mean()
df.std()
n1 = np.random.normal(0, 1, size=200) # N(0, 1)
n2 = np.random.normal(10, 2, size=200) # N(10, 4)
s = pd.Series(np.concatenate([n1, n2]))
s.describe()
s.plot.hist(bins=100, alpha=0.5, normed=True)
s.plot.kde(style='r-')

5. 散布图

散布图是把所有的点画在同一个坐标轴上的图像。是观察两个一维数据之间关系的有效的手段。

df = pd.DataFrame(np.random.rand(10, 4), columns=['a', 'b', 'c', 'd'])
df.plot.scatter(x='a', y='b');
df = pd.DataFrame({'a': np.concatenate([np.random.normal(0, 1, 200), np.random.normal(6, 1, 200)]),
                  'b': np.concatenate([np.random.normal(10, 2, 200), np.random.normal(0, 2, 200)]),
                  'c': np.concatenate([np.random.normal(10, 4, 200), np.random.normal(0, 4, 200)])})
df.describe()
df.plot.scatter(x='a', y='b')

6. 饼图

s = pd.Series(3 * np.random.rand(4), index=['a', 'b', 'c', 'd'], name='series')
s.plot.pie(figsize=(6,6))
s.plot.pie(labels=['AA', 'BB', 'CC', 'DD'], colors=['r', 'g', 'b', 'c'],
           autopct='%.2f', fontsize=20, figsize=(6, 6))
df = pd.DataFrame(3 * np.random.rand(4, 2), index=['a', 'b', 'c', 'd'], columns=['x', 'y'])
df.plot.pie(subplots=True, figsize=(9, 4))

7. 高级绘图

高级绘图函数在 pandas.tools.plotting 包里。

from pandas.tools.plotting import scatter_matrix
df = pd.DataFrame(np.random.randn(1000, 4), columns=['a', 'b', 'c', 'd'])
scatter_matrix(df, alpha=0.2, figsize=(6, 6), diagonal='kde');
s = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(np.linspace(-99 * np.pi, 99 * np.pi, num=1000)))
y = np.linspace(-99 * np.pi, 99 * np.pi, num=1000)
s.plot.
from pandas.tools.plotting import lag_plot

s = pd.Series(0.1 * np.random.rand(1000) + 0.9 * np.sin(np.linspace(-99 * np.pi, 99 * np.pi, num=1000)))
lag_plot(s)
from pandas.tools.plotting import autocorrelation_plot

s = pd.Series(0.7 * np.random.rand(1000) + 0.3 * np.sin(np.linspace(-9 * np.pi, 9 * np.pi, num=1000)))
autocorrelation_plot(s)

二. 股票数据分析

1. 分析波动幅度

datadir = 'yahoo-data'
fname = '002001.csv'
data = pd.read_csv(os.path.join(datadir, fname), index_col='Date', parse_dates=True)
## 使用 resample 针对复权收盘价进行重采样
adj_price = data['Adj Close']
resampled = adj_price.resample('m', how='ohlc')
(resampled.high - resampled.low) / resampled.low

2. 增长曲线

stockid = '600690.sz'
stockfile = '600690.csv'
ds = pd.read_csv(os.path.join('yahoo-data', stockfile), index_col='Date', parse_dates=True)
adj_price = ds['Adj Close']
adj_price.plot(figsize=(8, 6))

3. 增长倍数

计算最低价和最高价之间的收盘价比较,以及增长的倍数和年化复全增长率,这个反应的是一个股票最好的情况下的投资收益情况。

# 最高增长倍数
total_max_growth = adj_price.max() / adj_price.min()
# 最大年均复合增长率
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))

4. 当前增长倍数及复合增长率

计算上市时的收盘价与当前的收盘价比较,增长的倍数和年化复全增长率。

# 当前平均增长倍数
total_growth = adj_price.ix[0] / adj_price.ix[-1]
# 年复合增长倍数
old_date = adj_price.index[-1]
now_date = adj_price.index[0]
growth_per_year = total_growth ** (1.0 / (now_date.year - old_date.year))

5. 平均年化增长率

计算每年的增长率,然后再求平均值。也可以计算每月的增长率,再求平均值,可以看到更短的一些周期变化。

price_in_years = adj_price.to_period(freq='A').groupby(level=0).first()
price_in_years.plot(figsize=(8,6))
# 这里的关键信息:
# 计算年化收益率时,diff 应该要除以前一年的价格,即在前一年的价格的基础上上涨了多少,而不是在当前年的价格。
diff = price_in_years.diff()
rate_in_years =  diff / (price_in_years - diff)
rate_in_years.mean()
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='-')

三. 时间事件日志

个人时间统计工具。要点:

  • 使用 dida365.com 来作为 GTD 工具
  • 使用特殊格式记录事件类别和花费的时间,如: “[探索发现] 体验 iMac 开发环境 [3h]
  • 导出数据
  • 分析数据

1. 读取数据

from matplotlib.font_manager import FontManager
import subprocess    

def get_support_chinese_font():
    fm = FontManager()
    mat_fonts = set(f.name for f in fm.ttflist)

    output = subprocess.check_output('fc-list :lang=zh -f "%{family}/n"', shell=True)
    print '*' * 10, '系统可用的中文字体', '*' * 10
    print output
    zh_fonts = set(f.split(',', 1)[0] for f in output.split('/n'))
    available = mat_fonts & zh_fonts

    print '*' * 10, '可用的中文字体', '*' * 10
    for f in available:
        print f
    return available
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)
data.head()

2. 数据清洗

只关心己完成或己达成的事件,即 status != 0 的事件

  • 只需要 List NameTitle 字段
df = data[data['Status'] != 0].loc[:, ['List Name', 'Title']]
df.head()

3. 数据解析

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()
df.count()
start_date = df.index.min().date()
end_date = df.index.max().date()

3. 数据分析

时间总览
平均每天投资在自己身上的时间是多少?-> 全部时间 / 总天数

end_date - start_date
df['Duration'].sum() 
df['Duration'].sum() / (end_date - start_date).days

精力分配

tag_list = df.groupby(['Tag']).sum()
tag_list['Duration'].plot(kind='pie', figsize=(8, 8), fontsize=16, autopct='%1.2f%%')

专注力
长时间学习某项技能的能力

programming = df[df['Tag'] == '编程']
programming.head()
programming.resample('m', how='sum').to_period(freq='m').plot(kind='bar', figsize=(8, 8), fontsize=16)

连续时间的精力分配
以时间为横轴,查看精力分配。

# 为什么不直接使用 df.pivot()? 因为有重复的行索引,如 2016-05-23
date_tags = df.reset_index().groupby(['Due Date', 'Tag']).sum()
# 以 tag 作为列索引
dates = date_tags.reset_index().pivot(index='Due Date', columns='Tag', values='Duration')
# 补足连续时间,可以看到哪些天没有在学习
full_dates = dates.reindex(pd.date_range(start_date, end_date)).fillna(0)
# 画出柱状图
full_dates.plot(kind='bar', stacked=True, figsize=(16, 8))
full_dates.resample('m', how='sum').to_period('m').plot(kind='bar', stacked=True, figsize=(8, 8))

未经允许不得转载:作者:756-周同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《Python数据科学包(六)—–数据可视化和例子》 发布于2020-08-12

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录