Python数据分析第六章
图与图表
6.1 matplotlib
6.1.1 条形图
#!/Users/chenbryant/anaconda3/bin/python
import matplotlib.pyplot as plt
plt.style.use('ggplot')
customers = ['ABC', 'DEF', 'GHI', 'JKL', 'MNO']
customers_index = range(len(customers))
sale_amounts = [127, 90, 201, 111, 232]
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
# customer_index:设置条形左侧在x轴上的坐标
# sale_amounts:设置条形的高度。
# align='center' 设置条形与标签中间对齐
# color='darkblue'设置条形的颜色
ax1.bar(customers_index, sale_amounts, align='center', color='darkblue')
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
plt.xticks(customers_index, customers, rotation=0, fontsize='small')
plt.xlabel('Customer Name')
plt.ylabel('Sale Amount')
plt.title('Sale Amount per Customer')
plt.savefig('bar_plot.png', dpi=400, bbox_inches='tight')
plt.show()
6.1.2 直方图
#!/Users/chenbryant/anaconda3/bin/python
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
mu1, mu2, sigma = 100, 130, 15
# 创建两个正太分布变量x1和x2.x1均值为100,x2均值是130
x1 = mu1 + sigma*np.random.randn(10000)
x2 = mu2 + sigma*np.random.randn(10000)
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
# bins=50:每个变量的值被分为50份。alpha=0.5表示第二个直方图应该是透明的
n, bins, patches = ax1.hist(x1, bins=50, density=False, color='darkgreen')
n, bins, patches = ax1.hist(x2, bins=50, density=False, color='orange', alpha=0.5)
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
plt.xlabel('Bins')
plt.ylabel('Number of Values in Bin')
fig.suptitle('Histograms', fontsize=14, fontweight='bold')
ax1.set_title('Two Frequency Distributions')
plt.savefig('histogram.png', dpi=400, bbox_inches='tight')
plt.show()
6.1.3 折线图
#!/Users/chenbryant/anaconda3/bin/python
from numpy.random import randn
import matplotlib.pyplot as plt
plt.style.use('ggplot')
plot_data1 = randn(50).cumsum() # 按元素顺序累加
plot_data2 = randn(50).cumsum()
plot_data3 = randn(50).cumsum()
plot_data4 = randn(50).cumsum()
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
ax1.plot(plot_data1, marker=r'o', color=u'blue', linestyle='-', label='Blue Solid')
ax1.plot(plot_data2, marker=r'+', color=u'red', linestyle='--', label='Red Dashed')
ax1.plot(plot_data3, marker=r'*', color=u'green', linestyle='-.', label='Green Dash Dot')
ax1.plot(plot_data4, marker=r's', color=u'orange', linestyle=':', label='Orange Dotted')
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
ax1.set_title('Line Plots: Markers, Colors, and Linestyles')
plt.xlabel('Draw')
plt.ylabel('Random Number')
# loc='best'指示matplotlib根据图中空白部分将图例放在合适的位置
plt.legend(loc='best')
plt.savefig('line_plot.png', dpi=400, bbox_inches='tight')
plt.show()
6.1.4 散点图
#!/Users/chenbryant/anaconda3/bin/python
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
x = np.arange(start=1., stop=15., step=1.)
y_linear = x + 5. * np.random.randn(14)
y_quadratic = x**2 + 10. * np.random.randn(14)
fn_linear = np.poly1d(np.polyfit(x, y_linear, deg=1))
fn_quadratic = np.poly1d(np.polyfit(x, y_quadratic, deg=2))
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
ax1.plot(x, y_linear, 'bo', x, y_quadratic, 'go', x, fn_linear(x), 'b-', x, fn_quadratic(x), 'g-', linewidth=2.)
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
ax1.set_title('Scatter Plots with Best Fit Lines')
plt.xlabel('x')
plt.ylabel('f(x)')
plt.xlim((min(x)-1., max(x)+1.))
plt.ylim((min(y_quadratic)-10., max(y_quadratic)+10.))
plt.savefig('scatter_plot.png', dpi=400, bbox_inches='tight')
plt.show()
在第6行和第7行,通过随机数使数据与一条直线和一条二次曲线稍微偏离,第12中的 bo 表示图中的圆圈是蓝色,go 表示绿色圆圈, b- 表示蓝色实线,g-表示用绿色实线。
6.1.5 箱线图
箱线图可以表示出数据的最小值、第一四分位数、中位数、第三四分位数和最大值的图。箱体上下两端延伸出去的直线表示非离群点的最小值和最大值,在直线之外的点表示离群点。
#!/Users/chenbryant/anaconda3/bin/python
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
N = 500
normal = np.random.normal(loc=0.0, scale=1.0, size=N)
lognormal = np.random.lognormal(mean=0.0, sigma=1.0, size=N)
index_value = np.random.random_integers(low=0, high=N-1, size=N)
normal_sample = normal[index_value]
lognormal_sample = lognormal[index_value]
box_plot_data = [normal,normal_sample,lognormal,lognormal_sample]
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
box_labels = ['normal', 'normal_saple', 'lognormal', 'lognormal_sample']
ax1.boxplot(box_plot_data, notch=False, sym='.', vert=True, whis=1.5, showmeans=True, labels=box_labels)
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
ax1.set_title('Box Plots: Resampling of Two Distributions')
ax1.set_xlabel('Distribution')
ax1.set_ylabel('Value')
plt.savefig('box_plot.png', dpi=400, bbox_inches='tight')
plt.show()
第14行代码创建了一个列表box_labels用来存放每个箱线图的标签,在第15行代码中使用boxplot创建四个箱线图。notch=False表示箱体是矩形,而不是在中间收缩。sym='.'表示离群点使用圆点,vert=True表示箱体是垂直的,不是水平的。whis=1.5设定了直线从第一四分位数和第三四分位数延伸出的范围,showmeans=True表示箱体在显示中位数的同时也显示均值。labels=box_labels表示使用box_labels中的值来标记箱线图 。
6.2 pandas
pandas提供了一个可以作用于序列和数据框的函数plot,简化了创建图表的过程。plot函数默认创建折线图,还可以通过设置kind创建其他类型的图表。
下列代码展示了如何用pandas创建一对条形图和箱线图,并让他们并排放置:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('ggplot')
fig, axes = plt.subplots(nrows=1, ncols=2)
ax1, ax2 = axes.ravel()
data_frame = pd.DataFrame(np.random.rand(5, 3),
index=['Customer 1', 'Customer 2', 'Customer 3', 'Customer 4', 'Customer 5'],
columns=pd.Index(['Metric 1', 'Metric 2', 'Metric 3'], name='Metrics'))
# 创建条形图
data_frame.plot(kind='bar', ax=ax1, alpha=0.75, title='Bar Plot')
plt.setp(ax1.get_xticklabels(), rotation=45, fontsize=10)
plt.setp(ax1.get_yticklabels(), rotation=0, fontsize=10)
ax1.set_xlabel('Customer')
ax1.set_ylabel('Value')
ax1.xaxis.set_ticks_position('bottom')
ax1.yaxis.set_ticks_position('left')
colors = dict(boxes='DarkBlue', whiskers='Gray', medians='Red', caps='Black')
# 创建箱线图
data_frame.plot(kind='box', color=colors, sym='r.', ax=ax2, title='Box Plot')
plt.setp(ax2.get_xticklabels(), rotation=45, fontsize=10)
plt.setp(ax2.get_yticklabels(), rotation=0, fontsize=10)
ax2.set_xlabel('Metric')
ax2.set_ylabel('Value')
ax2.xaxis.set_ticks_position('bottom')
ax2.yaxis.set_ticks_position('left')
plt.savefig('pandas_plots.png', dpi=400, bbox_inches='tight')
plt.show()
6.3 seaborn
import seaborn as sns
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pylab import savefig
sns.set(color_codes=True)
# 直方图
x = np.random.normal(size=100)
sns.displot(x, bins=20, kde=False, rug=True, label="Histogram w/o Density")
# sns.utils.axlabel("Value", "Frequency")
sns.axlabel('Value', 'Frequency')
plt.title("Histogram of a Random Sample from a Normal Distribution")
plt.legend()
# 带有回归直线的散点图与单变量直方图
mean, cov = [5, 10], [(1, .5), (.5, 1)]
data = np.random.multivariate_normal(mean, cov, 200)
data_frame = pd.DataFrame(data, columns=["x", "y"])
sns.jointplot(x="x", y="y", data=data_frame, kind="reg").set_axis_labels("x", "y")
plt.suptitle("Joint Plot of Two Variables with Brivariate and Univariate Graphs")
# 成对变量之间的散点图与单变量直方图
iris = sns.load_dataset("iris")
sns.pairplot(iris)
# 按照某几个变量生成的箱线图
tips = sns.load_dataset("tips")
sns.factorplot(x="time", y="total_bill", hue="smoker", col="day", data=tips, kind="box", size=4, aspect=.5)
# 带有bootstrap置信区间的线性回归模型
sns.lmplot(x="total_bill", y="tip", data=tips)
# 带有bootstrap置信区间的逻辑斯蒂回归模型
tips["big_tip"] = (tips.tip / tips.total_bill) > .15
sns.lmplot(x="total_bill", y="big_tip", data=tips, logistic=True, y_jitter=.03).set_axis_labels("Total Bill", "Big Tip")
plt.title("Logistic Regression of Big Tip vs. Total Bill")
plt.show()
savefig("seaborn_plots.png")