900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > python簇状柱形图_使用Matplotlib绘制堆积条形图

python簇状柱形图_使用Matplotlib绘制堆积条形图

时间:2020-12-27 01:32:08

相关推荐

python簇状柱形图_使用Matplotlib绘制堆积条形图

条形图非常通用,易于阅读,并且相对容易构建。

就像任何可视化一样,条形图也有一些缺点,例如它们的可伸缩性较差。

条形图太多会使人感到难以阅读,尤其是在当我们处理层次化的类别,也就是当我们有需要可视化的组和子组时,这个问题更常见。

在这种情况下,堆积条形图是一个很好的选择,它让我们能更好地比较和分析数据。

在本文中,我们将探讨如何使用Python的Matplotlib构建这些可视化图形。

我将使用一个简单的数据集来保存全球的游戏副本的销售数据(虽然这个数据集已经过时,但它适合我们的示例)。

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltdf = pd.read_csv('../data/vgsales.csv')df.head()

我们接下来要将平台和地区的销售情况可视化。

将区域划分为列很有帮助,我们只需要按“Platform”对记录进行分组,并将NA_Sales到Global_Sales的值相加。

Groupby → Sum → Select Fields。

df_grouped = df.groupby('Platform').sum()[['NA_Sales','EU_Sales','JP_Sales','Other_Sales', 'Global_Sales']]df_grouped

数据中的值太多了,即使排除空记录,图表中的条形图也会太多。

我们为每个平台和区域绘制一个条形图,并查看结果。

# 定义图形fig, ax = plt.subplots(1, figsize=(16, 6))# 数字xx = np.arange(0, len(df_grouped.index))# 绘条形图plt.bar(x - 0.3, df_grouped['NA_Sales'], width = 0.2, color = '#1D2F6F')plt.bar(x - 0.1, df_grouped['EU_Sales'], width = 0.2, color = '#8390FA')plt.bar(x + 0.1, df_grouped['JP_Sales'], width = 0.2, color = '#6EAF46')plt.bar(x + 0.3, df_grouped['Other_Sales'], width = 0.2, color = '#FAC748')# 去除spinesax.spines['right'].set_visible(False)ax.spines['top'].set_visible(False)# x y细节plt.ylabel('Millions of copies')plt.xticks(x, df_grouped.index)plt.xlim(-0.5, 31)# 网格线ax.set_axisbelow(True)ax.yaxis.grid(color='gray', linestyle='dashed', alpha=0.2)#标题和图例plt.title('Video Game Sales By Platform and Region', loc ='left')plt.legend(['NA', 'EU', 'JP', 'Others'], loc='upper left', ncol = 4)plt.show()

正如我们所料,这张图很难阅读,那么让我们试试堆积条形图并做一些调整。

我们在绘制之前对值进行排序,这样可以更好地理解顺序,更容易比较条形图。我们将在“Global Sales”列中这样操作。

## 排序值df_grouped = df_grouped.sort_values('Global_Sales')df_grouped

在前文中,我们为每个区域构建了一个簇状条形图,其中宽度参数和x轴上的调整帮助我们拟合了每个平台的区域。

类似地,我们将为每个区域绘制堆积条形图。这次,我们用bottom/left参数告诉Matplotlib正在绘制的条形图是什么样。

plt.bar([1,2,3,4], [10,30,20,5])plt.bar([1,2,3,4], [3,4,5,6], bottom = [10,30,20,5])plt.show()plt.barh([1,2,3,4], [10,30,20,5])plt.barh([1,2,3,4], [3,4,5,6], left = [10,30,20,5])plt.show()

我们可以使用循环来绘制条形图,为第一个集合中的“bottom”参数传递一个零列表,并为下一个区域累积以下值。

fields = ['NA_Sales','EU_Sales','JP_Sales','Other_Sales']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']labels = ['NA', 'EU', 'JP', 'Others']# 图形和轴fig, ax = plt.subplots(1, figsize=(12, 10))# 绘图left = len(df_grouped) * [0]for idx, name in enumerate(fields): plt.barh(df_grouped.index, df_grouped[name], left = left, color=colors[idx]) left = left + df_grouped[name]# 标题、图例、标签plt.title('Video Game Sales By Platform and Region\n', loc='left')plt.legend(labels, bbox_to_anchor=([0.55, 1, 0, 0]), ncol=4, frameon=False)plt.xlabel('Millions of copies of all games')# 去除spinesax.spines['right'].set_visible(False)ax.spines['left'].set_visible(False)ax.spines['top'].set_visible(False)ax.spines['bottom'].set_visible(False)# 调整界限并绘制网格线plt.ylim(-0.5, ax.get_yticks()[-1] + 0.5)ax.set_axisbelow(True)ax.xaxis.grid(color='gray', linestyle='dashed')plt.show()

太好了,这比上一个图更易读。

目前我们的需求是比较平台的总销售和了解每个平台的组成。

可以比较不同字段的总数和同一条内的区域,而另一方面用不同的条形图来比较不同的地区可能会产生很大的误导。

在这种情况下,我们可以跨图比较NA区域,因为每个条形图都有相同的起始点,但是比较其他区域就不那么容易了。以X360为例,它的JP值比PS2低,但是很难比较其他值是比Wii高还是低。

假设我们更改栈的顺序,以Other Sales作为第一个条,并按Other Sales对记录进行排序。应该更容易分辨出哪个更重要。

## 排序值df_grouped = df_grouped.sort_values('Other_Sales')fields = ['Other_Sales', 'NA_Sales','EU_Sales','JP_Sales']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']labels = ['Others', 'NA', 'EU', 'JP']

在此可视化图形中有两个基本元素,即列堆栈中类别的顺序和行的顺序。

如果我们想要强调一个区域,可以选择字段对记录排序,并使用它作为最左边的条。

或者可以按总数对记录进行排序,并将堆栈与具有较高值的类别排序。

堆积条形图对于比较类别和可视化非常有用,我们可以利用它的更多优势。

可以集中展示整体的各个部分。为了达到这个目标,我们须准备数据并计算每个地区的销售比例。

fields = ['Other_Sales', 'NA_Sales','EU_Sales','JP_Sales']df_grouped = df.groupby('Platform').sum()# 在某些情况下,全球销售额并不等于所有地区的总和#所以我要重新计算df_grouped['Global_Sales'] = df_grouped[fields].sum(axis=1)# 为每个地区的全球销售额比例创建一个列for i in fields: df_grouped['{}_Percent'.format(i)] = df_grouped[i] / df_grouped['Global_Sales']df_grouped.sort_values('NA_Sales_Percent', inplace=True)df_grouped

我们几乎可以重复之前做的操作。

# 变量labels = ['NA', 'EU', 'JP', 'Others']colors = ['#1D2F6F', '#8390FA', '#6EAF46', '#FAC748']title = 'Video Game Sales By Platform and Region\n'subtitle = 'Proportion of Games Sold by Region'def plot_stackedbar_p(df, labels, colors, title, subtitle): fields = df.columns.tolist() # 图形和轴 fig, ax = plt.subplots(1, figsize=(12, 10))# 绘图 left = len(df) * [0] for idx, name in enumerate(fields): plt.barh(df.index, df[name], left = left, color=colors[idx]) left = left + df[name]# 标题和副标题 plt.title(title, loc='left') plt.text(0, ax.get_yticks()[-1] + 0.75, subtitle)# 图例 plt.legend(labels, bbox_to_anchor=([0.58, 1, 0, 0]), ncol=4, frameon=False)# 去除spines ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) ax.spines['top'].set_visible(False) ax.spines['bottom'].set_visible(False)# 格式化x xticks = np.arange(0,1.1,0.1) xlabels = ['{}%'.format(i) for i in np.arange(0,101,10)] plt.xticks(xticks, xlabels)# 调整界限并绘制网格线 plt.ylim(-0.5, ax.get_yticks()[-1] + 0.5) ax.xaxis.grid(color='gray', linestyle='dashed')plt.show()plot_stackedbar_p(df_filter, labels, colors, title, subtitle)

这是一个很好的可视化每个地区的销售比例的方法,也更容易比较其他类别,因为所有的条形图都在同一点结束。

在我看来,当只有两个类别时,用100%堆积条形图来可视化比例会更好,因为有一个固定的起点和另一个固定的终点,所以很容易将差异可视化并比较值。

最后我们尝试构建一个同时包含正值和负值的堆积条形图,为本例创建一个虚拟数据帧。

# 列表sales_revenue = [1230, 1240, 1170, 1050, 1380, 1480, 1400, 1410, 1360, 1415, 1530]interest_revenue = [150, 155, 159, 176, 290, 240, 195, 146, 180, 182, 210]fixed_costs = [-810, -810, -815, -815, -780, -780, -750, -750, -750, -770, -910] variable_costs =[-380, -410, -415, -370, -520, -655, -715, -670, -515, -510, -420]# dict的列表my_dict = {'sales_revenue': sales_revenue, 'interest_revenue': interest_revenue, 'fixed_costs': fixed_costs, 'variable_costs': variable_costs}# dict到dfresult_df = pd.DataFrame(my_dict)result_df

需求是每个月有一个正的条形图,分为销售和利息收入,和一个负的条形图,分为固定成本和可变成本。

我们需要把interest_revenue放在上面,所以在绘图时使用sales_revenue作为' bottom '参数。

我们希望将fixed_costs放在顶部作为负数,将用fixed_costs作为“bottom”参数来绘制variable_cost。

plt.bar(result_df.index, result_df['interest_revenue'], bottom = result_df['sales_revenue'], color = '#5E96E9', width =0.5)plt.bar(result_df.index, result_df['variable_costs'], bottom = result_df['fixed_costs'], color = '#E17979', width =0.5)

剩下的和我们之前做的非常相似。

fig, ax = plt.subplots(1, figsize=(16, 8))plt.bar(result_df.index, result_df['sales_revenue'], color = '#337AE3', width =0.5)plt.bar(result_df.index, result_df['interest_revenue'], bottom = result_df['sales_revenue'], color = '#5E96E9', width =0.5)plt.bar(result_df.index, result_df['fixed_costs'], color = '#DB4444', width =0.5)plt.bar(result_df.index, result_df['variable_costs'], bottom = result_df['fixed_costs'], color = '#E17979', width =0.5)# x和y的极限plt.xlim(-0.6, 10.5)plt.ylim(-1600, 2000)# 去除spinesax.spines['right'].set_visible(False)ax.spines['left'].set_visible(False)ax.spines['top'].set_visible(False)ax.spines['bottom'].set_visible(False)# 网格ax.set_axisbelow(True)ax.yaxis.grid(color='gray', linestyle='dashed', alpha=0.7)# x 标签xticks_labels = ['Jan', 'Fev', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov']plt.xticks(result_df.index , labels = xticks_labels)# 标题和图例legend_label = ['Sales Revenue', 'Interest Revenue', 'Variable Costs', 'Fixed Costs']plt.legend(legend_label, ncol = 4, bbox_to_anchor=([1, 1.05, 0, 0]), frameon = False)plt.title('My Company - \n', loc='left')plt.show()

就这样,我们创建了很多堆积条形图,并尝试用了不同的应用程序来实现这种方便的可视化技术。

资源:

Matplotlib 条形图(/3.3.3/api/_as_gen/matplotlib.pyplot.bar.html)

Matplotlib 堆积条形图(/3.1.1/gallery/lines_bars_and_markers/bar_stacked.html)

Matplotlib 水平条形图(/3.1.1/gallery/lines_bars_and_markers/bar_stacked.html)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。