Day3-《青春有你2》选手数据分析
最后更新于
这有帮助吗?
最后更新于
这有帮助吗?
基于第二天实践使用Python来爬去百度百科中《青春有你2》所有参赛选手的信息,进行数据可视化分析。
这个题目对新人来说相对也比较友好,已经事先给出了柱状图的例子,需要完成的是饼状图的例子:
# 如果需要进行持久化安装, 需要使用持久化路径, 如下方代码示例:
#!mkdir /home/aistudio/external-libraries
#!pip install matplotlib -t /home/aistudio/external-libraries
# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可:
# Also add the following code, so that every time the environment (kernel) starts, just run the following code:
import sys
sys.path.append('/home/aistudio/external-libraries')
# 下载中文字体
!wget https://mydueros.cdn.bcebos.com/font/simhei.ttf
# 将字体文件复制到matplotlib字体路径
!cp simhei.ttf /opt/conda/envs/python35-paddle120-env/lib/python3.7/site-packages/matplotlib/mpl-data/fonts/ttf/
# 一般只需要将字体文件复制到系统字体目录下即可,但是在aistudio上该路径没有写权限,所以此方法不能用
# !cp simhei.ttf /usr/share/fonts/
# 创建系统字体文件路径
!mkdir .fonts
# 复制文件到该路径
!cp simhei.ttf .fonts/
import matplotlib.pyplot as plt
import numpy as np
import json
import matplotlib.font_manager as font_manager
import os
#显示matplotlib生成的图形
%matplotlib inline
with open('data/data31557/20200422.json', 'r', encoding='UTF-8') as file:
json_array = json.loads(file.read())
#绘制小姐姐区域分布柱状图,x轴为地区,y轴为该区域的小姐姐数量
zones = []
for star in json_array:
zone = star['zone']
zones.append(zone)
print(len(zones))
print(zones)
zone_list = []
count_list = []
for zone in zones:
if zone not in zone_list:
count = zones.count(zone)
zone_list.append(zone)
count_list.append(count)
print(zone_list)
print(count_list)
# 设置显示中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
plt.figure(figsize=(20,15))
plt.bar(range(len(count_list)), count_list,color='r',tick_label=zone_list,facecolor='#9999ff',edgecolor='white')
# 这里是调节横坐标的倾斜度,rotation是度数,以及设置刻度字体大小
plt.xticks(rotation=45,fontsize=20)
plt.yticks(fontsize=20)
plt.legend()
plt.title('''《青春有你2》参赛选手''',fontsize = 24)
plt.savefig('/home/aistudio/work/result/bar_result.jpg')
plt.show()
109
['中国湖北', '中国四川', '中国山东', '中国浙江', '中国山东', '中国台湾', '中国陕西', '中国广东', '中国黑龙江', '中国上海', '中国四川', '中国山东', '中国安徽', '中国安徽', '中国安徽', '中国北京', '中国贵州', '中国吉林', '中国四川', '中国四川', '中国江苏', '中国山东', '中国山东', '中国山东', '中国山东', '中国江苏', '中国四川', '中国山东', '中国山东', '中国广东', '中国浙江', '中国河南', '中国安徽', '中国河南', '中国北京', '中国北京', '马来西亚', '中国湖北', '中国四川', '中国天津', '中国黑龙江', '中国四川', '中国陕西', '中国辽宁', '中国湖南', '中国上海', '中国贵州', '中国山东', '中国湖北', '中国黑龙江', '中国黑龙江', '中国上海', '中国浙江', '中国湖南', '中国台湾', '中国台湾', '中国台湾', '中国台湾', '中国山东', '中国北京', '中国北京', '中国浙江', '中国河南', '中国河南', '中国福建', '中国河南', '中国北京', '中国山东', '中国四川', '中国安徽', '中国河南', '中国四川', '中国湖北', '中国四川', '中国陕西', '中国湖南', '中国四川', '中国台湾', '中国湖北', '中国广西', '中国江西', '中国湖南', '中国湖北', '中国北京', '中国陕西', '中国上海', '中国四川', '中国山东', '中国辽宁', '中国辽宁', '中国台湾', '中国浙江', '中国北京', '中国黑龙江', '中国北京', '中国安徽', '中国河北', '马来西亚', '中国四川', '中国湖南', '中国台湾', '中国广东', '中国上海', '中国四川', '日本', '中国辽宁', '中国黑龙江', '中国浙江', '中国台湾']
['中国湖北', '中国四川', '中国山东', '中国浙江', '中国台湾', '中国陕西', '中国广东', '中国黑龙江', '中国上海', '中国安徽', '中国北京', '中国贵州', '中国吉林', '中国江苏', '中国河南', '马来西亚', '中国天津', '中国辽宁', '中国湖南', '中国福建', '中国广西', '中国江西', '中国河北', '日本']
[6, 14, 13, 6, 9, 4, 3, 6, 5, 6, 9, 2, 1, 2, 6, 2, 1, 4, 5, 1, 1, 1, 1, 1]
# 不存在result文件夹就新建一个
if not os.path.exists('work/result'):
os.makedirs('work/result')
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
# 去掉字符串的kg单位并转换成浮点型数字
weights_num = df['weight'].str.rstrip('kg').astype(float)
# 使其切分为不同的[,)半开半闭区间
weights_interval=pd.cut(weights_num,[0,45,50,55,60],right=False)
# 先进行计数再进行排序
weights=weights_interval.value_counts().sort_values(ascending=False)
# 用percent让饼图随着比例而突出 比例越大越突出
weights_percent=weights_interval.value_counts(normalize=True)/4
# 创建特定大小的画布
fig,ax=plt.subplots(figsize=(20,15))
# 引入新的颜色主题
# theme = plt.get_cmap('jet')
# ax.set_prop_cycle("color", [theme(1. * i / len(weights))
# for i in reversed(range(len(weights)))])
# 将weights键值的值提取出来和键拼接字符串格式
weights_count=[str(val) for val in weights.values.tolist()]
# 将键categories标签转换成string并加上单位
weights_labels=weights.index.astype(str)
weights_labels=['<45kg' if label[label.find('[')+1:label.find(',')]=='0'
else label[label.find('[')+1:label.find(',')]+'kg~'+label[label.find(',')+2:label.find(')')]+'kg'
for label in weights_labels]
# 键和值拼接饼图的label
pie_labels=[label+':'+count+'个' for _,(label,count) in enumerate(zip(weights_labels, weights_count))]
fig,l,p=plt.pie(weights, explode=weights_percent,
labels=pie_labels,autopct='%1.1f%%',
shadow=True, startangle=90,textprops={'fontsize': 18})
ax.axis('equal') # 保证比例相等确保画出来的是一个圆而不是椭圆
# 加上图表标注
ax.legend(labels=weights.index)
plt.savefig('/home/aistudio/work/result/pie_result01.jpg')
plt.show()
详细的解释在代码中已有,不过这个饼图相对来说并没什么难度,为了提升难度可以把其做成每个kg各一片的饼图:
labels = 'Frogs', 'Hogs', 'Dogs', 'Logs'
sizes = [15, 30, 45, 10]
explode = (0, 0.1, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
# 先进行计数再进行排序
weights=df['weight'].value_counts().sort_values(ascending=False)
# 用percent让饼图随着比例而突出 比例越大越突出
weights_percent=df['weight'].value_counts(normalize=True)
# 创建特定大小的画布
fig,ax=plt.subplots(figsize=(20,15))
# 由于原来的color颜色会重复 因此需要引入新的颜色主题
theme = plt.get_cmap('hsv')
ax.set_prop_cycle("color", [theme(1. * i / len(weights))
for i in range(len(weights))])
# 将weights键值的值提取出来和键拼接字符串格式
weights_count=[str(val) for val in weights.values.tolist()]
# 由于labels会相互遮挡 因此将其旋转
fig,l,p=plt.pie(weights, explode=weights_percent,labels=weights.index+':'+weights_count+'个',
autopct='%1.1f%%',rotatelabels=True,
shadow=True, startangle=90,textprops={'fontsize': 18})
ax.axis('equal') # 保证比例相等确保画出来的是一个圆而不是椭圆
threshold=0.01 # 旋转比例阈值
#旋转比例过小的切片防止比例文字遮挡
for index,text in enumerate(p):
if weights_percent[index]<threshold:
rot = text.get_rotation()
text.set_rotation(rot-90-(1-rot//180)*180)
ax.legend(labels=weights.index)
plt.savefig('/home/aistudio/work/result/pie_result01.jpg')
plt.show()
可以看到当切片数量提升时,饼图的难度明显增加,首先是默认的颜色主题颜色会不够用而导致颜色重复,需要使用
plt.get_cmap('hsv')
引入新的颜色主题,其次饼图的label会相互遮挡,因此需要plt.pie(weights,rotatelabels=True)
将其进行旋转,甚至连小概率0.9%的文本都会相互遮挡,需要设置一个阈值
threshold=0.01 # 旋转比例阈值
#旋转比例过小的切片防止比例文字遮挡
for index,text in enumerate(p):
if weights_percent[index]<threshold:
rot = text.get_rotation()
text.set_rotation(rot-90-(1-rot//180)*180)
将小概率的文本也进行旋转(由于全部概率文本都进行旋转不太美观因此作罢)。