python图表之pygal入门篇

0
0
0
1. 云栖社区>
2. 博客>
3. 正文

## python图表之pygal入门篇

GGYQ 2017-10-20 08:58:00 浏览848

# pygal的简单使用

pygal是一个SVG图表库。SVG是一种矢量图格式。全称Scalable Vector Graphics -- 可缩放矢量图形。

## 模拟掷骰子

``````import random

class Die:
"""
一个骰子类
"""
def __init__(self, num_sides=6):
self.num_sides = num_sides

def roll(self):
return random.randint(1, self.num_sides)
``````

``````import pygal

die = Die()
result_list = []
# 掷1000次
for roll_num in range(1000):
result = die.roll()
result_list.append(result)

frequencies = []
# 范围1~6，统计每个数字出现的次数
for value in range(1, die.num_sides + 1):
frequency = result_list.count(value)
frequencies.append(frequency)

# 条形图
hist = pygal.Bar()
hist.title = 'Results of rolling one D6 1000 times'
# x轴坐标
hist.x_labels = [1, 2, 3, 4, 5, 6]
# x、y轴的描述
hist.x_title = 'Result'
hist.y_title = 'Frequency of Result'
# 添加数据， 第一个参数是数据的标题
# 保存到本地，格式必须是svg
hist.render_to_file('die_visual.svg')
``````

## 同时掷两个骰子

``````die_1 = Die()
die_2 = Die()

result_list = []
for roll_num in range(5000):
# 两个骰子的点数和
result = die_1.roll() + die_2.roll()
result_list.append(result)

frequencies = []
# 能掷出的最大数
max_result = die_1.num_sides + die_2.num_sides

for value in range(2, max_result + 1):
frequency = result_list.count(value)
frequencies.append(frequency)

# 可视化
hist = pygal.Bar()
hist.title = 'Results of rolling two D6 dice 5000 times'
hist.x_labels = [x for x in range(2, max_result + 1)]
hist.x_title = 'Result'
hist.y_title = 'Frequency of Result'
# 添加数据
# 格式必须是svg
hist.render_to_file('2_die_visual.svg')
``````

## 处理json数据--世界人口地图

``````[
{
"Country Name":"Arab World",
"Country Code":"ARB",
"Year":"1960",
"Value":"92496099"
},
...
``````

``````import json

filename = r'F:\Jupyter Notebook\matplotlib_pygal_csv_json\population.json'
with open(filename) as f:

cc_populations = {}
for pop_dict in pop_data:
if pop_dict['Year'] == '2015':
country_name = pop_dict['Country Name']
# 有些值是小数，先转为float再转为int
population = int(float(pop_dict['Value']))
print(country_name + ': ' + population)
``````

``````Arab World: 392168030
Caribbean small states: 7116360
Central Europe and the Baltics: 103256779
Early-demographic dividend: 3122757473.68203
East Asia & Pacific: 2279146555
...
``````

### 获取两个字母的国别码

`pip install pygal_maps_world`就可以了

`from pygal_maps_world.i18n import COUNTRIES`这样就导入了, COUNTRIES是一个字典，键是两位国别码，值是具体国家名。

``````key -> value
af Afghanistan
af Afghanistan
al Albania
al Albania
dz Algeria
dz Algeria
ao Angola
``````

``````def get_country_code(country_name):
"""
根据国家名返回两位国别码
"""
for code, name in COUNTRIES.items():
if name == country_name:
return code
return None
``````

### 世界人口地图绘制

``````import json

from pygal_maps_world.i18n import COUNTRIES
from pygal_maps_world.maps import World
# 颜色相关
from pygal.style import RotateStyle
from pygal.style import LightColorizedStyle

def get_country_code(country_name):
"""
根据国家名返回两位国别码
"""
for code, name in COUNTRIES.items():
if name == country_name:
return code
return None

filename = r'F:\Jupyter Notebook\matplotlib_pygal_csv_json\population.json'
with open(filename) as f:

cc_populations = {}
for pop_dict in pop_data:
if pop_dict['Year'] == '2015':
country_name = pop_dict['Country Name']

# 有些值是小数，先转为float再转为int
population = int(float(pop_dict['Value']))
code = get_country_code(country_name)
if code:
cc_populations[code] = population

# 为了使颜色分层更加明显
cc_populations_1,cc_populations_2, cc_populations_3 = {}, {}, {}
for cc, population in cc_populations.items():
if population < 10000000:
cc_populations_1[cc] = population
elif population < 1000000000:
cc_populations_2[cc] = population
else:
cc_populations_3[cc] = population

wm_style = RotateStyle('#336699', base_style=LightColorizedStyle)
world = World(style=wm_style)
world.title = 'World Populations in 2015, By Country'
world.render_to_file('world_population_2015.svg')
``````

• `cc_populations`是一个dict，里面存放了两位国别码与人口的键值对。
• `cc_populations_1,cc_populations_2, cc_populations_3`这是3个字典，把人口按照数量分阶梯，人口一千万以下的存放在`cc_populations_1`中，一千万~十亿级别的存放在`cc_populations_2`中，十亿以上的存放在`cc_populations_3`中，这样做的目的是使得颜色分层更加明显，更方便找出各个阶梯里人口最多的国家。由于分了三个层次，在添加数据的的时候也add三次，把这三个字典分别传进去。
• `world = World(style=wm_style)`这是一个地图类，导入方法`from pygal_maps_world.maps import World`
• `wm_style = RotateStyle('#336699', base_style=LightColorizedStyle)`这里修改了pygal默认的主题颜色，第一个参数是16进制的RGB颜色，前两位代表R，中间两位代表G，最后两位代表B。数字越大颜色越深。第二个参数设置基础样式为亮色主题，pygal默认使用较暗的颜色主题，通过此方法可以修改默认样式。

<div class="image-package">

</div>

``````# 传入的参数country_name是json数据中的，可能与COUNTRIES里面的国家名不一致，按照上面的代码直接就返回None，导致绘图时这个国家的人口数据空白
if country_name == 'Yemen, Rep':
return 'ye'
``````

## 使用Web API分析数据

``````{
"total_count": 1767997,
"incomplete_results": false,
"items": [{
{
"id": 21289110,
"name": "awesome-python",
"full_name": "vinta/awesome-python",
"owner": {
...
},
...
"html_url": "https://github.com/vinta/awesome-python",
...
"stargazers_count": 35234,
...

}, {...}
...]
}
``````

``````import requests

url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
response = requests.get(url)
# 200为响应成功
print(response.status_code, '响应成功！')
response_dict = response.json()

total_repo = response_dict['total_count']
repo_list = response_dict['items']
print('总仓库数: ', total_repo)
print('top', len(repo_list))
for repo_dict in repo_list:
print('\nName: ', repo_dict['name'])
print('Stars: ', repo_dict['stargazers_count'])
print('Repo: ', repo_dict['html_url'])
print('Description: ', repo_dict['description'])
``````

``````200 响应成功！

top 30

Name:  awesome-python
Owner:  vinta
Stars:  35236
Repo:  https://github.com/vinta/awesome-python
Description:  A curated list of awesome Python frameworks, libraries, software and resources

Name:  httpie
Owner:  jakubroztocil
Stars:  30149
Repo:  https://github.com/jakubroztocil/httpie
Description:  Modern command line HTTP client – user-friendly curl alternative with intuitive UI, JSON support, syntax highlighting, wget-like downloads, extensions, etc.  https://httpie.org

Name:  thefuck
Owner:  nvbn
Stars:  28535
Repo:  https://github.com/nvbn/thefuck
Description:  Magnificent app which corrects your previous console command.
...
``````

### pygal可视化数据

``````import requests

import pygal
from pygal.style import LightColorizedStyle, LightenStyle

url = 'https://api.github.com/search/repositories?q=language:python&sort=stars'
response = requests.get(url)
# 200为响应成功
print(response.status_code, '响应成功！')
response_dict = response.json()

total_repo = response_dict['total_count']
repo_list = response_dict['items']
print('总仓库数: ', total_repo)
print('top', len(repo_list))

names, plot_dicts = [], []
for repo_dict in repo_list:
names.append(repo_dict['name'])
# 加上str强转，因为我遇到了'NoneType' object is not subscriptable (: 说明里面有个没有此项, 是NoneType
plot_dict = {
'value' : repo_dict['stargazers_count'],
# 有些描述很长很长，选最前一部分
'label' : str(repo_dict['description'])[:200]+'...',
}
plot_dicts.append(plot_dict)

# 改变默认主题颜色，偏蓝色
my_style = LightenStyle('#333366', base_style=LightColorizedStyle)
# 配置
my_config = pygal.Config()
# x轴的文字旋转45度
my_config.x_label_rotation = -45
# 隐藏左上角的图例
my_config.show_legend = False
# 标题字体大小
my_config.title_font_size = 30
# 副标签，包括x轴和y轴大部分
my_config.label_font_size = 20
# 主标签是y轴某数倍数，相当于一个特殊的刻度，让关键数据点更醒目
my_config.major_label_font_size = 24
# 限制字符为15个，超出的以...显示
my_config.truncate_label = 15
# 不显示y参考虚线
my_config.show_y_guides = False
# 图表宽度
my_config.width = 1000

# 第一个参数可以传配置
chart = pygal.Bar(my_config, style=my_style)
chart.title = 'Most-Starred Python Projects on GitHub'
# x轴的数据
chart.x_labels = names
# 加入y轴的数据，无需title设置为空，注意这里传入的字典，
# 其中的键--value也就是y轴的坐标值了
chart.render_to_file('most_stars_python_repo.svg')
``````

GGYQ
+ 关注