第九章绘图与可视化
% matplotlib notebook
9.1 简明matplotlib API入门
使用Jupyter notebook时有个细节需要注意,在每个单元格运行后,图表被重置,因此对于更复杂的图表,你必须将所有的绘图命令放在单个的notebook单元格中
import matplotlib. pyplot as plt
import numpy as np
data = np. arange( 10 )
data
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
plt. plot( data)
9.1.1 图片与子图
matplotlib所绘制的图位于图片(Figure)对象中 pyplot.subplots选项
参数 描述 nrows 子图的行数 ncols 子图的列数 sharex 所有子图使用相同的x轴刻度(调整xlim会影响所有子图) sharey 所有子图使用相同的y轴刻度(调整ylim会影响所有子图) subplot_ kw 传入add_ subplot 的关键字参数字典,用于生成子图 **fig_ _kW 在生成图片时使用的额外关键字参数,例如plt. subplots (2,2,figsize= (8,6))
fig = plt. figure( )
ax1 = fig. add_subplot( 2 , 2 , 1 )
ax2 = fig. add_subplot( 2 , 2 , 2 )
ax3 = fig. add_subplot( 2 , 2 , 3 )
plt. plot( np. random. randn( 50 ) . cumsum( ) , 'k--' )
_ = ax1. hist( np. random. randn( 100 ) , bins= 20 , color= 'k' , alpha= 0.3 )
ax2. scatter( np. arange( 30 ) , np. arange( 30 ) + 3 * np. random. randn( 30 ) )
fig, axes = plt. subplots( 2 , 3 , sharex= True , sharey= True )
9.1.1.1 调整子图周围的间距
你可以使用图对象上的subplots_adjust方法更改间距,也可以用作顶层函数
plt. subplots_adjust( left= None , bottom= None , right= None , top= None
, wspace= None , hspace= None , )
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( wspace= 0 , hspace= 0 )
9.1.2 颜色、标记和线类型
from numpy. random import randn
fig = plt. figure( )
plt. plot( randn( 30 ) . cumsum( ) , 'ko--' )
fig = plt. figure( )
data = np. random. randn( 30 ) . cumsum( )
plt. plot( data, 'k--' , label= 'Default' )
plt. plot( data, 'k-' , drawstyle= 'steps-post' , label= 'step-post' )
plt. legend( loc= 'best' )
9.1.3 刻度、标签和图例
9.1.3.1 设置标题、轴
要改变x轴刻度,最简单的方式是使用set_xticks和set_xticklabels set_xticks表示在数据范围内设定刻度的位置,默认情况下,这些刻度也有标签
fig = plt. figure( )
ax = fig. add_subplot( 1 , 1 , 1 )
ax. plot( np. random. randn( 1000 ) . cumsum( ) )
ticks = ax. set_xticks( [ 0 , 250 , 500 , 750 , 1000 ] )
labels = ax. set_xticklabels( [ 'one' , 'two' , 'three' , 'four' , 'five' ] , rotation= 30 , fontsize= 'small' )
ax. set_title( 'My first matplotlib plot' )
ax. set_xlabel( 'stages' )
9.1.3.2 添加图例
from numpy. random import randn
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( loc= 'best' )
ax. text( x, y, 'hello world' , family= 'monospace' , fontsize= 10 )
9.1.4 注释与子图加工
使用text、arrow和annote方法来添加注释和文本。 text在图表上给定的坐标(x, y),根据可选的定制样式绘制文本
data = pd. read_csv( 'examples/spx.csv' , index_col= 0 , parse_dates= True )
spx = data[ 'SPX' ]
from datetime import datetime
fig = plt. figure( )
ax = fig. add_subplot( 1 , 1 , 1 )
spx. plot( ax= ax, style= 'k-' )
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)
plt. savefig( 'figpath.png' , dpi= 400 , bbox_inches= 'tight' )
9.1.5 将图片保存到文件
你可以使用plt.savefig将活动图片保存到文件。这个方法等价于图片对象的savefig实例方法
from io import BytesIO
buffer = BytesIO( )
plt. savefig( buffer )
plt_data = buffer . getvalue( )
9.1.6 matplotlib设置
使用rc方法是使用Python编程修改配置的一种方式
9.2 使用pandas和seaborn绘图
9.2.1 折线图
默认情况下,plot()绘制的是折线图 Series对象的索引传入matplotlib作为绘图的x轴,你可以通过传入use_index=False来禁用这个功能 x轴的刻度和范围可以通过xticks和xlim选项进行调整,相应地y轴使用yticks和ylim进行调整。 Series.plot方法参数
参数 描述 label 图例标签绘图所用的matplotib子图对象;如果没传值,则使用当前活动的matplotlib子图 style 传给matplotlib的样式字符串,比如’ko–’ alpha 图片不透明度(从0到1) kind 可以是’area’. ‘bar’. ‘barh’. ’ density’、‘hist’.,kde’. ’ line’. ‘pie’ logy 在y轴上使用对数缩放 use_ index 使用对象索引刻度标签 rot 刻度标签的旋转(0 到360) xticks 用于x轴刻度的值 yticks 用于y轴刻度的值 xlim x轴范围(例如[0,10]) ylim y轴范围 grid 展示轴网格(默认是打开的)
s = pd. Series( np. random. randn( 10 ) . cumsum( ) ,
index= np. arange( 0 , 100 , 10 ) )
s. plot( )
s
0 0.168491
10 -0.301518
20 -1.247281
30 -0.589754
40 -0.974903
50 -0.322050
60 -0.330096
70 -0.729736
80 -1.298080
90 -1.207302
dtype: float64
df = pd. DataFrame( np. random. randn( 10 , 4 ) . cumsum( 0 ) ,
columns= [ 'A' , 'B' , 'C' , 'D' ] ,
index= np. arange( 0 , 100 , 10 ) )
df. plot( )
df
A B C D 0 0.353917 -0.100911 2.919896 -0.008181 10 1.240468 -0.237893 2.654006 -0.272069 20 0.024472 -2.666705 3.998338 0.151660 30 1.694991 -3.006836 3.546508 1.095049 40 1.567156 -2.611247 2.958782 0.730146 50 2.757183 -4.033031 5.663888 0.594940 60 3.556481 -1.969082 6.819354 1.949167 70 4.763156 -1.863628 6.163130 3.080424 80 5.675488 -3.051450 6.532281 3.146377 90 4.219759 -1.997804 7.616493 5.069851
```python df.plot.line() ``` ### 9.2.2 柱状图 - plot.bar()和plot.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
df. plot. bar( )
df. plot. bar( stacked= True , alpha= 0.5 )
df. plot. barh( stacked= True , alpha= 0.5 )
tips = pd. read_csv( 'examples/tips.csv' )
tips. head( )
total_bill tip smoker day time size 0 16.99 1.01 No Sun Dinner 2 1 10.34 1.66 No Sun Dinner 3 2 21.01 3.50 No Sun Dinner 3 3 23.68 3.31 No Sun Dinner 2 4 24.59 3.61 No Sun Dinner 4
pay_counts = pd. crosstab( tips[ 'day' ] , tips[ 'size' ] )
pay_counts
size 1 2 3 4 5 6 day Fri 1 16 1 1 0 0 Sat 2 53 18 13 1 0 Sun 0 39 15 18 3 1 Thur 1 48 4 5 1 3
party_counts = pay_counts. loc[ : , 2 : 5 ]
party_counts
size 2 3 4 5 day Fri 16 1 1 0 Sat 53 18 13 1 Sun 39 15 18 3 Thur 48 4 5 1
party_counts. sum ( 1 )
day
Fri 18
Sat 85
Sun 75
Thur 58
dtype: int64
party_pcts = party_counts. div( party_counts. sum ( 1 ) , axis= 0 )
party_pcts. plot. bar( )
party_pcts
size 2 3 4 5 day Fri 0.888889 0.055556 0.055556 0.000000 Sat 0.623529 0.211765 0.152941 0.011765 Sun 0.520000 0.200000 0.240000 0.040000 Thur 0.827586 0.068966 0.086207 0.017241
import seaborn as sns
tips
total_bill tip smoker day time size 0 16.99 1.01 No Sun Dinner 2 1 10.34 1.66 No Sun Dinner 3 2 21.01 3.50 No Sun Dinner 3 3 23.68 3.31 No Sun Dinner 2 4 24.59 3.61 No Sun Dinner 4 ... ... ... ... ... ... ... 239 29.03 5.92 No Sat Dinner 3 240 27.18 2.00 Yes Sat Dinner 2 241 22.67 2.00 Yes Sat Dinner 2 242 17.82 1.75 No Sat Dinner 2 243 18.78 3.00 No Thur Dinner 2
244 rows × 6 columns
tips[ 'tip_pct' ] = tips[ 'tip' ] / ( tips[ 'total_bill' ] - tips[ 'tip' ] )
sns. barplot( x= 'tip_pct' , y= 'day' , data= tips, orient= 'h' )
tips. head( )
total_bill tip smoker day time size tip_pct 0 16.99 1.01 No Sun Dinner 2 0.063204 1 10.34 1.66 No Sun Dinner 3 0.191244 2 21.01 3.50 No Sun Dinner 3 0.199886 3 23.68 3.31 No Sun Dinner 2 0.162494 4 24.59 3.61 No Sun Dinner 4 0.172069
sns. barplot( x= 'tip_pct' , y= 'day' , data= tips, orient= 'h' , hue= 'time' )
sns. set ( style= 'white' )
9.2.3 直方图和密度图
直方图是一种条形图,用于给出值频率的离散显示。 数据点被分成离散的,均匀间隔的箱,并且绘制每个箱中数据点的数量。
tips[ 'tip_pct' ] . plot. hist( bins= 50 )
tips[ 'tip_pct' ] . plot. density( )
comp1 = np. random. normal( 0 , 1 , size= 200 )
comp1[ : 10 ]
array([ 1.79433075, 0.71950576, 1.85644046, 1.70894088, 0.15187961,
-0.65322128, 1.82576072, 0.41054884, -0.3166894 , -0.27848755])
comp2 = np. random. normal( 10 , 2 , size= 200 )
comp2[ : 10 ]
array([ 9.17557046, 12.23272092, 10.79859503, 8.79727061, 10.2600498 ,
9.93102067, 7.30060627, 12.17173317, 11.23735906, 8.1658837 ])
values = pd. DataFrame( np. concatenate( [ comp1, comp2] ) )
values. head( )
0 0 1.794331 1 0.719506 2 1.856440 3 1.708941 4 0.151880
sns. distplot( values, bins= 100 , color= 'k' )
D:\Anaconda3\lib\site-packages\seaborn\distributions.py:2557: FutureWarning: `distplot` is a deprecated function and will be removed in a future version. Please adapt your code to use either `displot` (a figure-level function with similar flexibility) or `histplot` (an axes-level function for histograms).
warnings.warn(msg, FutureWarning)
sns. displot( values)
9.2.4 散点图或点图
点图或散点图可以用于检验两个一维数据序列之间的关系
macro = pd. read_csv( 'examples/macrodata.csv' )
macro. head( )
year quarter realgdp realcons realinv realgovt realdpi cpi m1 tbilrate unemp pop infl realint 0 1959.0 1.0 2710.349 1707.4 286.898 470.045 1886.9 28.98 139.7 2.82 5.8 177.146 0.00 0.00 1 1959.0 2.0 2778.801 1733.7 310.859 481.301 1919.7 29.15 141.7 3.08 5.1 177.830 2.34 0.74 2 1959.0 3.0 2775.488 1751.8 289.226 491.260 1916.4 29.35 140.5 3.82 5.3 178.657 2.74 1.09 3 1959.0 4.0 2785.204 1753.7 299.356 484.052 1931.3 29.37 140.0 4.33 5.6 179.386 0.27 4.06 4 1960.0 1.0 2847.699 1770.5 331.722 462.199 1955.5 29.54 139.6 3.50 5.2 180.007 2.31 1.19
data = macro[ [ 'cpi' , 'm1' , 'tbilrate' , 'unemp' ] ]
data. head( )
cpi m1 tbilrate unemp 0 28.98 139.7 2.82 5.8 1 29.15 141.7 3.08 5.1 2 29.35 140.5 3.82 5.3 3 29.37 140.0 4.33 5.6 4 29.54 139.6 3.50 5.2
trans_data = np. log( data) . diff( ) . dropna( )
trans_data. head( )
cpi m1 tbilrate unemp 1 0.005849 0.014215 0.088193 -0.128617 2 0.006838 -0.008505 0.215321 0.038466 3 0.000681 -0.003565 0.125317 0.055060 4 0.005772 -0.002861 -0.212805 -0.074108 5 0.000338 0.004289 -0.266946 0.000000
import matplotlib. pyplot as plt
plt. rcParams[ 'font.sans-serif' ] = [ 'Microsoft YaHei' ]
plt. rcParams[ 'axes.unicode_minus' ] = False
sns. regplot( 'm1' , 'unemp' , data= trans_data)
plt. title( '这是标题,太多英文字母了,不想打' )
sns. pairplot( trans_data, diag_kind= 'kde' , plot_kws= { 'alpha' : 0.2 } )
9.2.5 分面网格和分类数据
seaborn拥有一个有效的内建函数factorplot,它可以简化多种分面绘图
tips. head( )
total_bill tip smoker day time size tip_pct 0 16.99 1.01 No Sun Dinner 2 0.063204 1 10.34 1.66 No Sun Dinner 3 0.191244 2 21.01 3.50 No Sun Dinner 3 0.199886 3 23.68 3.31 No Sun Dinner 2 0.162494 4 24.59 3.61 No Sun Dinner 4 0.172069
sns. factorplot( x= 'day' , y= 'tip_pct' , hue= 'time' , col= 'smoker' , kind = 'bar' , data= tips[ tips. tip_pct< 1 ] )
sns. factorplot( x= 'day' , y= 'tip_pct' , row= 'time' , col= 'smoker' , kind = 'bar' , data= tips[ tips. tip_pct< 1 ] )
sns. factorplot( x= 'day' , y= 'tip_pct' , kind = 'box' , data= tips[ tips. tip_pct< 1 ] )
9.3 其他Python可视化工具
借助像Bokeh(http://bokeh.pydata.org/)和Plotly(https://github.com/plotly/plotly.py)这样的工具,在web浏览器中创建动态的、交互式图像的工作现在已经可以实现。
9.4 本章小结