python+matplotlib绘制饼图,可视化性别比例&地区比例实例(函数封装+条件分支思想应用)

又是一次tensorflow课作业来啦,老师要求的是用wxpy+matplotlib进行微信好友性别比例+好友所在地区的统计,但是由于wxpy登不上网页版微信,所以最后搞成瞎编好友数据并且用matplotlib给它们画图。封装了一个饼图绘制函数draw(),感觉以后还可以用到于是就写篇博客。
p.s.全部代码放在最后,欢迎抱走~

一、目标
使用wxpy从个人微信网页版获取好友信息(不能实现),进行统计分析并使用matplotlib绘制可视化饼图。绘制过程中存在重复的部分要求使用函数封装,实现代码的复用。
图一:微信好友性别统计,显示男女各占比例。
图二:微信好友地区统计,选择所在人数最多的10个地区,按顺序显示地区名+比例。

二、思路
1.数据来源:由于无法登录网页版微信,自定义好友数据(列表类型)
2.封装为函数:将使用matplotlib模块绘图的过程抽象为draw()函数,实现代码复用。
3.设置条件分支并绘图:按照性别统计与地区统计的特征,设计参数处理过程。使用命令行交互,用户可选择两种图表中的一种,并进行绘制。

三、步骤与原理
1 导入模块与数据
matplotlib库用于图表绘制,导入matplotlib.pyplot模块。
由于无法登陆网页版微信,自定义数据以进行后续的统计和可视化分析。将数据存为字典的形式,注意无序设置以检测后续统计功能中的排序过程。

import matplotlib.pyplot as plt
#from wxpy import *
#bot = Bot(cache_path = True)
#friends_stat = bot.friends().stats()

#由于无法登陆微信网页版而自定义好友信息数据
friends_stat={'sex':{1:34,2:55}, # 性别
            'province':{'北京':30,'上海':19,'山东':108,'黑龙江':4,
            '浙江':2,'广东':6,'广西':3,'江苏':7,
            '内蒙古':1,'西藏':1,'吉林':2,'新疆':1,
            '四川':11,'湖北':2,'湖南':2,'辽宁':5} # 省份
            } 

2 定义绘图函数draw()
定义函数的依据:在使用matplotlib绘制饼图时,绘制过程可复用,各饼图之间的区别在于1.饼图标签集labels 2.各标签对应的数值大小sizes。由labels可计算出饼图的数据项数(分块数),由sizes可计算出饼图分割的比例。
于是将传入参数设置为[labels]和[sizes],其他参数或为固定,或可由传入参数计算得到。

经过计算得到的参数:
(1)items_count: 饼图项数,为labels列表的长度,使用len()计算。
(2)colors:预存10种颜色到color_list,根据items_count确定颜色数量匹配的colors列表,使用切片操作。
(2)explode:使用合适的一次项系数0.3,保证间隙根据项数设置递增。
关于ios系统设置中文字体的参数,请参考:https://www.cnblogs.com/wanghui-garcia/p/11195925.html

#定义绘图函数
def draw(labels,sizes):
    plt.figure(figsize=(6,9))   #调节图形大小
    colors_list = ['yellowgreen','lightgrey','navy','blue','yellow','red','green','pink','indigo','lightskyblue']
    items_count=len(labels)
    colors=colors_list[:items_count]
    explode=[0]*items_count #将某一块分割出来,值越大分割出来的间隙越大
    for i in range(items_count): 
        explode[i]=i*0.03
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
    #plt.rcParams['font.sans-serif'] = ['SongTi SC']#ios系统
    plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)
    #patches饼图的返回值,texts1饼图外label的文本,texts2饼图内部的文本
    patches,text1,text2 = plt.pie(sizes,
                        explode=explode,
                        labels=labels,
                        colors=colors,
                        autopct = '%3.2f%%', #数值保留固定小数位
                        shadow=False,#无阴影设置
                        startangle=90,#逆时针起始角度设置
                        pctdistance=0.6)#数值距圆心半径倍数距离
    plt.axis('equal')# x,y轴刻度设置一致,保证饼图为圆形
    plt.show()

3根据用户选择绘图
设置条件分支,使用命令行交互。若用户输入为“1”,则绘制好友性别比例图;若用户输入为“2”,则绘制好友地区比例图。
#选择想要的图表并显示

choice=input("输入1显示好友性别统计,输入2显示好友地区统计:")

3.1好友性别饼图的绘制
(1)对不同性别的好友进行计数。
(2)文字输出计数结果到命令行。
(3)向draw()函数传入代表两种性别的标签列表[sex_labels],以及男性朋友和女性朋友两项对应的人数列表[sex_sizes]。
(4)绘制饼图。

#若用户选择性别图示
if choice=="1": 
    #设置性别图示所需参数
    for sex,count in friends_stat['sex'].items():
        if sex == 1:
            print("男性朋友:",count)
            male_count = count
        elif sex == 2:
            print("女生朋友:",count)
            female_count = count#统计图
    sex_labels = ['Male','Female']# 定义标签
sex_sizes = [male_count,female_count] # 每块的值

    #使用函数传参绘图
draw(sex_labels,sex_sizes)

3.2 好友所在地区饼图的绘制
(1)对好友所在地区进行计数。
(2)文字输出计数结果到命令行。
(3)对计数结果进行排序处理,并使用切片截取所在人数最多的10个地区对应的好友人数。向draw()函数传入代表不同地区的标签列表[loc_labels],以及所在不同地区对应的人数列表[loc_sizes]。
(4)绘制饼图。

#若用户选择地区图示
if choice=="2": 
    #设置地区图示所需参数
    friend_loc = [] 
    for province,count in friends_stat['province'].items():
        if province != "":
            friend_loc.append([province,count])
    friend_loc.sort(key=lambda x:x[1],reverse=True)#对人数倒序
    loc_labels = []
    loc_sizes = []
    for item in friend_loc[:10]:
        print(item[0],item[1])#打印人数最多的10个地区
        loc_labels.append(item[0])
        loc_sizes.append(item[1])
    #使用函数传参绘图
    draw(loc_labels,loc_sizes)

四、操作效果
1.运行程序
2.输入“1”,进行好友性别统计。
命令行:
在这里插入图片描述
绘图窗口:
在这里插入图片描述

3.输入“2”
命令行:
在这里插入图片描述
绘图窗口:
在这里插入图片描述

全部代码:

import matplotlib.pyplot as plt
#from wxpy import *
#bot = Bot(cache_path = True)
#friends_stat = bot.friends().stats()

#由于无法登陆微信网页版而自定义好友信息数据
friends_stat={'sex':{1:34,2:55}, # 性别
			'province':{'北京':30,'上海':19,'山东':108,'黑龙江':4,
			'浙江':2,'广东':6,'广西':3,'江苏':7,
			'内蒙古':1,'西藏':1,'吉林':2,'新疆':1,
			'四川':11,'湖北':2,'湖南':2,'辽宁':5} # 省份
			} 

#定义绘图函数
def draw(labels,sizes):
    plt.figure(figsize=(6,9))	#调节图形大小
    colors_list = ['yellowgreen','lightgrey','navy','blue','yellow','red','green','pink','indigo','lightskyblue']
    items_count=len(labels)
    colors=colors_list[:items_count]
    explode=[0]*items_count	#将某一块分割出来,值越大分割出来的间隙越大
    for i in range(items_count): 
        explode[i]=i*0.03
    plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换sans-serif字体)
    #plt.rcParams['font.sans-serif'] = ['SongTi SC']#ios系统
    plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)
    #patches饼图的返回值,texts1饼图外label的文本,texts2饼图内部的文本
    patches,text1,text2 = plt.pie(sizes,
						explode=explode,
						labels=labels,
						colors=colors,
						autopct = '%3.2f%%', #数值保留固定小数位
						shadow=False,#无阴影设置
						startangle=90,#逆时针起始角度设置
						pctdistance=0.6)#数值距圆心半径倍数距离
    plt.axis('equal')# x,y轴刻度设置一致,保证饼图为圆形
    plt.show()

#选择想要的图表并显示
choice=input("输入1显示好友性别统计,输入2显示好友地区统计:")

#若用户选择性别图示
if choice=="1": 
    #设置性别图示所需参数
    for sex,count in friends_stat['sex'].items():
	    if sex == 1:
		    print("男性朋友:",count)
		    male_count = count
	    elif sex == 2:
		    print("女生朋友:",count)
		    female_count = count#统计图
    sex_labels = ['Male','Female']# 定义标签
    sex_sizes = [male_count,female_count] # 每块的值
    #使用函数传参绘图
    draw(sex_labels,sex_sizes)

#若用户选择地区图示
if choice=="2": 
    #设置地区图示所需参数
    friend_loc = [] 
    for province,count in friends_stat['province'].items():
	    if province != "":
		    friend_loc.append([province,count])
    friend_loc.sort(key=lambda x:x[1],reverse=True)#对人数倒序
    loc_labels = []
    loc_sizes = []
    for item in friend_loc[:10]:
	    print(item[0],item[1])#打印人数最多的10个地区
	    loc_labels.append(item[0])
	    loc_sizes.append(item[1])
    #使用函数传参绘图
    draw(loc_labels,loc_sizes)

代码分块+思路讲解
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述在这里插入图片描述


版权声明:本文为qq_43655453原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。