又是一次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)
代码分块+思路讲解