绘图与可视化

1. 简明 matplotlib 入门

%matplotlib notebook                  # 在 jupyter notebook 中使用交互式绘图
import matplotlib.pyplot as plt
import numpy as np
data = np.arange(10)
plt.plot(data)

1.1 图片与子图

  1. matplotlib所绘制的图片位于 Figure 对象中,可以使用 plt.figure 生成一个图片,但该图片是一个空白;
  2. 使用 add_subplot 创建一个或多个子图;
  3. 输入绘图命令 plt.plot 后,默认在最后一个图片和子图上进行绘制;
  4. fig.add_subplot 返回的是 Axes Subplot 对象,因此可以直接在其他空白的子图上调用对象的实例方法进行绘图;
fig = plt.figure()
ax1 = fig.add_subplot(2, 2, 1)        # 生成 2*2 的子图,ax1 为第一个子图
ax2 = fig.add_subplot(2, 2, 2)        # 生成 2*2 的子图,ax2 为第二个子图
ax3 = fig.add_subplot(2, 2, 3)        # 生成 2*2 的子图,ax3 为第三个子图
plt.plot(np.random.randn(50).cumsum(), 'k--')        # 'k--' 是用于绘制黑色分段线的 style 选项
_ = ax1.hist(np.random.randn(100), bins=20, color='k', alpha=0.3)        # 在 ax1 上绘制直方图
ax2.scatter(np.arange(30), np.arange(30) + 3 * np.random.randn(30))        # 在 ax2 上绘制散点图
  1. 创建子图网格的快捷方法:plt.subplots,返回新的 Figure 对象和子图对象组成的数组,该数组可以像二维数组一样进行索引(如 axes[0, 1])
  2. 调整子图周围的间距:subplots_adjust
fig, axes = plt.subplots(2, 2, sharex=True, sharey=True)
for i in range(2):
    for j in range(2):
        axes[i, j].hist(np.random.randn(500), bins=50, color='k', alpha=0.5)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None, wspace=0, hspace=0)        # 默认都为 None
  1. pyplot.subplots 选项:
参数描述
nrows子图的行数
ncols子图的列数
sharex所有子图使用相同的 x 轴刻度
sharey所有子图使用相同的 y 轴刻度
subplot_kw传入 add_subplot 的关键字参数字典,用于生成子图**fig_kw生成图片时使用的额外关键字参数,例如 plt.subplots(2, 2, figsize=(8, 6))

1.2 颜色、标记和线类型

  1. 既可以使用如 “k–” 这样的字符串来指定颜色和线类型等,也可以使用参数名更显式地表达:
# 样式字符串中线类型、标记类型必须跟在颜色后面
plt.plot(np.random.randn(30).cumsum(), 'ko--')
# 如下为更显式的表达
plt.plot(np.random.randn(30).cumsum(), color='k', linestyle='--', marker='o')
plt.plot(np.random.randn(30).cumsum(), color='k', linestyle='dashed', marker='o')
  1. 对于折线图,后续的点默认是线性内插的,可以通过 drawstyle 进行更改;
  2. 要生成图例,必须调用 plt.legend,无论是否传递了 label
data = np.random.randn(30).cumsum()
plt.plot(data, 'k--', label='Default')
plt.plot(data, 'k-', drawstyle='steps-post', label='steps-post')
plt.legend(loc='best')

1.3 刻度、标签和图例

  1. pyplot 的刻度等方法有两种方式:在没有传递函数参数的时候为获取当前参数值(如 plt.xlim() 返回当前 x 轴绘图范围);在传入函数参数的时候为设定参数值(如 plt.xlin([0, 10]) 会将 x 轴的范围设置为 0 到 10)
  2. pyplot 的每个方法都对应于 subplot 实例的两个方法,如 xlim 对应于 ax.get_xlim 和 ax.set_xlim;
  3. 设置标题、轴标签、刻度和刻度标签示例:
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(randn(1000).cumsum())
ticks = ax.set_xticks([0, 250, 500, 750, 1000])		# 设置 x 轴刻度
labels = ax.set_xticklabels(['one', 'two', 'three', 'four', 'five'], 
				rotation=30, fontsize='small')	# rotation 旋转标签
ax.set_title('My first matplotlib plot')		# 设置标题
ax.set_xlabel('Stages')					# 设置 x 轴名称
  1. 轴类型的 set 方法允许批量设置绘图属性:
props = {
        'title': 'My first matplotlib plot',
        'xlabel': 'Stages'
        }
ax.set(**props)
  1. 添加图例:添加每个图标时传递 label 参数(若不要图例中的元素,则不要传递 label 参数),并调用 ax.legend() 或 plt.legend():
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(randn(1000).cumsum(), 'k', label='one')
ax.plot(randn(1000).cumsum(), 'k--', label='two')
ax.plot(randn(1000).cumsum(), 'k.', label='three')
ax.legend()

1.4 注释与子图加工

  1. 在图表上绘制自己的注释,其中可能包含文本(text)、箭头(arrow)以及其他图形。注释可以同时绘制文本和箭头,以 2007 年以来标普 500 的收盘价为例,在图标中标注从 2008 年到 2009 年金融危机中的重要日期:
from datetime import datetime

fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

data = pd.read_csv(r'C:\Users\Raymone\Data Analysis\examples\spx.csv', 
			index_col=0, parse_dates=True)		# data is a DataFrame
spx = data['SPX']			# spx is a Series

spx.plot(ax=ax, style='k-')		# a black full line
crisis_data = [
    (datetime(2007, 10, 11), 'Peak of bull market'),
    (datetime(2008, 3, 12), 'Bear Stearns Fails'),
    (datetime(2008, 9, 15), 'Lehman Bankruptcy')
]					# a list of tuples

# annotate can draw the labels on the appointed x and y
# spx.asof(date) returns the last value that is not NA before or on the appointed date
# xy is the location of the arrow tip, xytext is the location of the left of the text 
# horizontalalignment and verticalalignment decide the left and the top of the text are aligned to 'xytext'(文本左上角对齐至指定坐标)
for date, label in crisis_data:
    ax.annotate(label, xy=(date, spx.asof(date) + 75),
               xytext=(date, spx.asof(date) + 225),
               arrowprops=dict(facecolor='black', headwidth=4, width=2, headlength=4),
               horizontalalignment='left', verticalalignment='top'
               )
# 放大 2007~2010 年
ax.set_xlim(['1/1/2007', '1/1/2011'])
ax.set_ylim([600, 1800])

ax.set_title('Important dates in the 2008-2009 financial crisis')               
  1. matplotlib 含有多种常见图形的对象,这些对象的引用是 matplotlib.patches。想要在图标中添加图形时,需要生成 patch (补丁)对象 shp,并调用 ax.add_patch(shp)将它加入到子图中:
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)

rect = plt.Rectangle((0.2, 0.75), 0.4, 0.15, color='k', alpha=0.3)
circ = plt.Circle((0.7, 0.2), 0.15, color='b', alpha=0.3)
pgon = plt.Polygon([[0.15, 0.15], [0.35, 0.4], [0.2, 0.6]], color='g', alpha=0.5)

ax.add_patch(rect)
ax.add_patch(circ)
ax.add_patch(pgon)

1.5 将图片保存到文件

  1. 保存至硬盘:
plt.savefig('figpath.png', dpi=400, bbox_inches='tight')
  1. 保存至文件型对象,如 BytesIO:
from io import BytesIO
buffer = BytesIO()
plt.savefig(buffer)
plot_data = buffer.getvalue()
  1. figure.savefig 选项:
参数描述
fname包含文件路径或Python文件型对象的字符串。图片格式是从文件扩展名中推断出来的
dpi每英寸点数的分辨率,默认为100
facecolor, edgecolor子图之外的图形背景颜色,默认情况下是 ‘w’ 白色
format文件格式
bbox_inches要保存的图片范围,如果传递 tight,则去掉图片周围空白的部分

1.6 matplotlib 设置

设置全局参数来定制图片,包括图形大小,子图间距,颜色,字体大小和网格样式等:

plt.rc('figure', figsize=(10, 10))
font_options = {'family': 'monospace', 'weight': 'bold', 'size': 'small'}
plt.rc('font', **font_options)

2. 使用 pandas 和 seaborn 绘图

2.1 折线图

  1. Series 和 DataFrame 都有一个 plot 方法,用于绘制基本图形,默认绘制折线图:
s = pd.Series(np.random.randn(10).cumsum(), index=np.arange(0, 100, 10))
s.plot()    # index 作为 x 轴,使用 use_index=False 来禁用
df = pd.DataFrame(np.random.randn(10, 4).cumsum(0), 
			columns=['A', 'B', 'C', 'D'], index=np.arange(0, 100, 10))
df.plot()
  1. Series.plot 方法参数
参数描述
label图例标签
ax绘图所用的 matplotlib 子图对象,如果没有传值,则使用当前活动的 matplotlib 子图
style传给 matplotlib 的样式字符串,如 ‘ko–’
alpha图片不透明度(从 0 到 1)
kind可以是 ‘area’, ‘bar’, ‘barh’, ‘density’, ‘hist’, ‘kde’, ‘line’, ‘pie’
logy在 y 轴上使用对数缩放
use_index使用对象索引刻度标签,默认为 True
rot刻度标签的旋转(0~360)
xticks用于 x 轴刻度的值
yticks用于 y 轴刻度的值
xlimx 轴范围
ylimy 轴范围
grid展示轴网格,默认打开
  1. DataFrame 的 plot 参数:
参数描述
subplots将 DataFrame 的每一列绘制在独立的子图中
sharex若 subplots=True,则共享相同的 x 轴、刻度和范围
sharey若 subplots=True,则共享相同的 y 轴
figsize用于生成图片尺寸的元组
title标题字符串
legend添加子图图例,默认为 True
sort_columns按字母顺序绘制各列,默认情况下使用已有的列顺序

2.2 柱状图

  1. plot.bar()和plot.barh()可以分别绘制垂直和水平柱状图,Series 或 DataFrame 的索引将会被用作 x 轴刻度(bar)或 y轴刻度(barh)
fig, axes = plt.subplots(2, 1)
data = pd.Series(np.random.rand(16), index=list('abcdefghijklmnop'))
data.plot.bar(ax=axes[0], color='k', alpha=0.7)
data.plot.barh(ax=axes[1], color='k', alpha=0.7)
df = pd.DataFrame(np.random.rand(6, 4), 
			index=['one', 'two', 'three', 'four', 'five', 'six'], 
			columns=pd.Index(['A', 'B', 'C', 'D'], name='Genus'))
df.plot.bar()					# 列名称 Genus 将被用作图例标题
df.plot.barh(stacked=True, alpha=0.5)         	# stacked 代表堆积柱形图			
  1. 绘制一个堆积柱形图,用于展示每个派对在每天的数据点占比:
tips = pd.read_csv(r'C:/Users/Raymone/Data Analysis/examples/tips.csv')
party_counts = pd.crosstab(tips['day'], tips['size'])	# crosstab 为交叉表
party_counts = party_counts.loc[:, 2:5]			# 1 人 和 6 人的派对较少,去掉
party_pcts = party_counts.div(party_counts.sum(1), axis=0)	# 标准化至和为1
party_pcts.plot.bar()
  1. 对于绘图前需要聚合或汇总的数据,使用 seaborn 包可以使工作更为简单,如下示例使用 seaborn 进行按星期日期计算小费百分比:
import seaborn as sns
tips['tip_pct'] = tips['tip']/(tips['total_bill'] - tips['tip'])
sns.barplot(x='tip_pct', y='day', data=tips)
# 柱子的值是 tip_pct 的平均值,黑线代表的是 95% 的置信区间
# 使用 hue 参数通过一个额外的分类值将数据分离
sns.barplot(x='tip_pct', y='day', hue='time', data=tips)	

2.3 直方图和密度图

  1. 直方图是一种条形图,用于给出值频率的离散显示。数据点被分成均匀的离散的箱,并绘制每个箱中数据点的数量。使用 plot.hist 方法制作小费占总费用百分比的直方图:
tips['tip_pct'].plot.hist(bins=50)
  1. 密度图是一种与直方图相关的图标类型,通过计算可能产生观测数据的连续概率分布估计而产生。通常的做法是将这种分布近似为“内核”的混合,也就是像正态分布那样简单的分布。因此密度图也称为内核密度估计图(KDE):
tips['tip_pct'].plot.density()
  1. sns.distplot 方法可以绘制直方图和连续密度估计,如下为两个不同标准正态分布组成的双峰分布:
comp1 = np.random.normal(0, 1, size=200)
comp2 = np.random.normal(10, 2, size=200)
values = pd.Series(np.concatenate([comp1, comp2]))
sns.distplot(values, bins=100, color='k')

2.4 散点图或点图

  1. 点图或散点图可以用于检验两个一维数据之间的关系,使用seaborn 的 regplot 方法,该方法可以绘制散点图,并拟合出一条线性回归线。如下为计算数据集中一些变量的对数差:
macro = pd.read_csv(r'C:/Users/Raymone/Data Analysis/examples/macrodata.csv')
data = macro[['cpi', 'm1', 'tbilrate', 'unemp']]
trans_data = np.log(data).diff().dropna()
sns.regplot('m1', 'unemp', data=trans_data)
plt.title('Changes in log %s versus log %s' % ('m1', 'unemp'))
  1. 使用 pairplot 绘制成对图(或散点图矩阵),其中在对角线上放置的是每个变量的直方图或密度估计值:
sns.pairplot(trans_data, diag_kind='kde', plot_kws={'alpha': 0.2})

2.5 分面网格和分类数据

分面网格是利用多种分组变量对数据进行可视化的方式:

# factorplot 函数已重命名为 catplot 函数
sns.catplot(x='day', y='tip_pct', hue='time', col='smoker', kind='bar', 
		data=tips[tips.tip_pct < 1])
# 扩展分面网格
sns.catplot(x='day', y='tip_pct', row='time', col='smoker', kind='bar', 
		data=tips[tips.tip_pct < 1])
# 箱型图
sns.catplot(x='tip_pct', y='day', kind='box', data=tips[tips.tip_pct < 0.5])				
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值