最近在imooc上搜索数据分析,学习了一个python工程师体验营,主要内容是:
python基础 + python读取excel数据 + Echarts图表可视化
记录一下课程内容,巩固记忆(完整代码与结果在最下方)。
python运行后,在浏览器里输入 http://127.0.0.1:8080 + 你在python文件中定义的url
如本文示例:http://127.0.0.1:8080/chart 即可在网页中看到我们创建的图表
Echarts简介:
Apache ECharts是一个基于 JavaScript 的开源可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表。
Echarts拥有丰富的功能,可以通过模板实现各种数据图表可视化,并且官网有许多示例,可以直接复制代码进行修改,实现自己的需要。
官网示例:
点击一个图,左边可以直接查看代码。
引用Echarts
进入Echarts官网Apache ECharts下载解压后,找到echarts.min文件,复制到所需项目的文件夹中,为它单独创立一个文件夹,再创建html的文件夹和.py文件。
使用Echarts读取数据
需要的框架:web.py和xlrd
在python中安装web.py和xlrd模块
import web
import xlrd
(一)web.py
web.py 是一个开源的轻量级Python web框架,无论用于什么用途都是没有限制的,而且相当的小巧,属于轻量级的web框架。
web.py的完整示例代码:
import web
urls = (
'/(.*)', 'hello'
)
app = web.application(urls, globals())
class hello:
def GET(self, name):
if not name:
name = 'World'
return 'Hello, ' + name + '!'
if __name__ == "__main__":
app.run()
第一部分 URL映射
我们需要告诉web.py如何组织url,比如:
# 路由配置
urls = (
'/chart', 'chart'
)
元组格式为:('路径','处理类')
( '/' )是一个匹配url的正则表达式,有三种类型:
1. URL完全匹配
'/chart','Chart',由Chart类处理 http://127.0.0.1:8080/chart
2. URL模糊匹配
'/chart/\d+','Chart',由Chart类处理 http://127.0.0.1:8080/chart/1,chart/后接一个数字的url
3. URL带组匹配
'/chart/(\d+)','Chart',由Chart类处理 http://127.0.0.1:8080/chart/1,chart/后接数字的url,带组匹配与模糊匹配的区别是在正则表达式外部添加一个括号,即表达匹配一组。
带组匹配会匹配chart后的参数,模糊匹配则不会
第二部分 匹配模板
新建一个目录(命名为templates),在该目录下新建一个以html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
</body>
</html>
在顶部加上def with表示模板将从这后面取值(实例中name为sales_data)
$def with(name)
回到我们的.py文件,在url配置后加上代码:
app = web.application(urls, globals())
render = web.template.render('templates/')
application基本来说就是创建一个应用urls参数指明了网站url与应用执行的函数间的一个映射。
render则是告诉web.py到模板目录中去查找模板,最后在类里写return render.模板( ),如:
return render.chart(sales_data=sales_data, source_data=source_data,
source_title=source_all_title,
source_stat_data=source_stat_data,
clue_data=clue_data,
clue_title=clue_title)
最后再完成class中的GET方法用来处理相对应的url的GET请求。
class chart:
def GET(self):
我的web.py部分代码(此处还没有加入读取数据的代码,是无法直接运行的):
import web
import xlrd
# 路由配置
urls = (
'/chart', 'chart'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class chart:
def GET(self):
return render.chart(sales_data=sales_data, source_data=source_data,
source_title=source_all_title,
source_stat_data=source_stat_data,
clue_data=clue_data,
clue_title=clue_title)
if __name__ == '__main__':
app.run()
(二)xlrd
xlrd是Python语言中,读取Excel的扩展工具。
1. 打开Excel文件读取数据
data = xlrd.open_workbook('excelFile.xls')
2. 使用技巧
获取一个工作表
table = data.sheets()[0] #通过索引顺序获取
table = data.sheet_by_index(0) #通过索引顺序获取
table = data.sheet_by_name(u'Sheet1')#通过名称获取
获取整行和整列的值(数组)
table.row_values(i)
table.col_values(i)
获取行数和列数
nrows = table.nrows
ncols = table.ncols
循环行列表数据
for i in range(nrows ):
print table.row_values(i)
组成最终导入模板的数据
使用Echarts时常用到name:value类型的字典,可直接读取某行或某列数据
# 读取excel数据
work_book = xlrd.open_workbook('data.xls')
# sheet 1
work_sheet_1 = work_book.sheet_by_index(0)
sales_data = {
'category': work_sheet_1.row_values(0),
'data': work_sheet_1.row_values(1)
}
在html模板中将category作为y轴,data作为x轴
xAxis:{
type:'category',
data:sales_data['category']
},
yAxis:{},
series:[
{
'name':'销售额',
type:'bar',
data:sales_data['data'],
在饼状图中常用for循环结合append读取数据,构成我们最终导入到模板类的字典,如:
分别读取第四行的标题和第五行的数据,将标题与数据对应存放到source_data里
# sheet 2
work_sheet_2 = work_book.sheet_by_index(1)
source_data = []
source_legend = []
source_title = work_sheet_2.row_values(3)
source_value = work_sheet_2.row_values(4)
for idx in range(len(source_title)):
tmp_data = {
'name': source_title[idx],
'value': source_value[idx]
}
source_data.append(tmp_data)
Echarts基本用法
1. 在<body></body>内引入echarts文件(charts文件放在static文件夹里)
<script src="static/echarts.min.js"></script>
2. 定义div容器存放图表
<body>
<!-- 实例中 id 为 main 的 div 用于包含 ECharts 绘制的图表 -->
<div id="main" style="width: 600px;height:400px;"></div>
</body>
在本文实例中,用了一些模板,一共定义了三幅图,下文介绍的是第一幅图sales_wrap:
<div class="container-fluid">
<div class="row">
<div class="col-lg-12" id="sales_wrap" style="min-height: 400px;">
</div>
<div class="col-lg-6" id="source_wrap" style="min-height: 400px;">
</div>
<div class="col-lg-6" id="order_wrap" style="min-height: 400px;">
</div>
</div>
</div>
3.设置配置信息(javascript部分)
基本格式
ECharts 库使用 json 格式来配置:
echarts.init(document.getElementById('main')).setOption(option);
使用var声明变量,此处option_1是第一幅图,其他入title等属性在下文进行介绍。
var option_1 = {
title:{
},
xAxis:{
},
yAxis:{},
series:[
],
tooltip:{
},
toolbox:{
}
};
chart_1.setOption(option_1);
补充第一幅图的数据源:
var sales_data = $:sales_data;
在html文件最上方加入声明:
$def with(sales_data)
接下来设置横纵坐标轴、工具栏等属性,即可画好第一幅图。
标题
title:{
text:'71公司月销售额',
subtext:'销售额(单位:万)'
},
X轴
可以直接写x轴代表的信息如:
xAxis: {
data: ["衬衫","羊毛衫","雪纺衫","裤子","高跟鞋","袜子"]
}
也可以连接我们导入的数据:取category这个列表的值作为横坐标
xAxis:{
type:'category',
data:sales_data['category']
},
Y轴
yAxis: {}
系列列表
series:[
{
'name':'销售额',
type:'bar',
data:sales_data['data'],
markPoint:{
data:[
{type:"max",name:"最大值"},
{type:"min",name:"最小值"}
]
},
markLine:{
data:[
{type:'average',name:'平均值'}
]
}
}
],
提示信息
tooltip:{
trigger:'axis'
},
将鼠标放到坐标轴上会有详细数字信息显示
工具栏
toolbox:{
show:true,
feature:{
dataView:{},
magicType:{type:['line','bar']},
restore:{},
saveAsImage:{}
}
show:true代表工具箱显示,图表右上角会出现工具箱选项,但要在feature中写了才会出现。
feature是一些功能属性,其中:
dataView是具体数值显示,点击后:
magicType是图表类型转换,这里定义了我们的图表可以转换为条形图bar或者折线图line:
,点击Line Chart
再点击Bar Chart可回到原图,或者直接点击Restore还原
最后一个如名字一般,是保存图片 ,点击后即可下载图片
到这里第一幅图已经完成啦。
最终结果展示与代码
我一共画了三幅图,格式参照第一幅图即可。
python代码:
import web
import xlrd
# 路由配置
urls = (
'/chart', 'chart'
)
app = web.application(urls, globals())
render = web.template.render('templates/')
class chart:
def GET(self):
# 读取excel数据
work_book = xlrd.open_workbook('data.xls')
# sheet 1
work_sheet_1 = work_book.sheet_by_index(0)
sales_data = {
'category': work_sheet_1.row_values(0),
'data': work_sheet_1.row_values(1)
}
print(sales_data)
# sheet 2
work_sheet_2 = work_book.sheet_by_index(1)
source_data = []
source_legend = []
source_title = work_sheet_2.row_values(3)
source_value = work_sheet_2.row_values(4)
for idx in range(len(source_title)):
tmp_data = {
'name': source_title[idx],
'value': source_value[idx]
}
source_data.append(tmp_data)
source_stat_data = []
source_stat_title = work_sheet_2.row_values(0, 0, 3)
source_stat_value = work_sheet_2.row_values(1, 0, 3)
for idx in range(len(source_stat_title)):
tmp_stat_data = {
'name': source_stat_title[idx],
'value': source_stat_value[idx]
}
source_stat_data.append(tmp_stat_data)
# 两个list进行合并
source_all_title = source_stat_title + source_title
# sheet 3
work_sheet_3 = work_book.sheet_by_index(2)
clue_data = []
clue_title = work_sheet_3.row_values(0)
clue_value = work_sheet_3.row_values(1)
for idx in range(len(clue_title)):
tmp_data = {
'name': clue_title[idx],
'value': clue_value[idx]
}
clue_data.append(tmp_data)
return render.chart(sales_data=sales_data, source_data=source_data,
source_title=source_all_title,
source_stat_data=source_stat_data,
clue_data=clue_data,
clue_title=clue_title)
if __name__ == '__main__':
app.run()
html代码:
$def with(sales_data,source_data,source_title,source_stat_data,clue_data,clue_title)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>画图</title>
<!-- Bootstrap -->
<link href="static/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-lg-12" id="sales_wrap" style="min-height: 400px;">
</div>
<div class="col-lg-6" id="source_wrap" style="min-height: 400px;">
</div>
<div class="col-lg-6" id="order_wrap" style="min-height: 400px;">
</div>
</div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="static/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="static/bootstrap.min.js"></script>
<script src="static/echarts.min.js"></script>
<script type="text/javascript">
// 基于准备好的dom,初始化echarts实例
var chart_1 = echarts.init(document.getElementById('sales_wrap'));
var sales_data = $:sales_data;
var option_1 = {
title:{
text:'71公司月销售额',
subtext:'销售额(单位:万)'
},
xAxis:{
type:'category',
data:sales_data['category']
},
yAxis:{},
series:[
{
'name':'销售额',
type:'bar',
data:sales_data['data'],
markPoint:{
data:[
{type:"max",name:"最大值"},
{type:"min",name:"最小值"}
]
},
markLine:{
data:[
{type:'average',name:'平均值'}
]
}
}
],
tooltip:{
trigger:'axis'
},
toolbox:{
show:true,
feature:{
dataView:{},
magicType:{type:['line','bar']},
restore:{},
saveAsImage:{}
}
}
};
chart_1.setOption(option_1);
var chart_2 = echarts.init(document.getElementById('source_wrap'));
var source_data = $:source_data;
var source_title = $:source_title;
var source_stat_data = $:source_stat_data;
var option_2 = {
tooltip:{
trigger:'item',
formatter:'{a}<br/>{b}:{c}({d}%)'
},
legend:{
orient:'vertical',
left:10,
data:source_title
},
series:[
{
name:'访问来源',
type:'pie',
radius:['40%','55%'],
data:source_data,
label:{
formatter:'{a|{a}}\n {hr|}\n {b|{b}}: {c}{per|{d}}%',
borderColor:'aaa',
borderWidth:1,
borderRadius:4,
backgroundColor:'#eee',
rich:{
a:{
color:'#999',
lineHeight:22,
align:'center'
},
hr:{
borderColor:'#aaa',
width:'100%',
borderWidth:0.5,
height:0
},
b:{
fontSize:16,
lineHeight:33
},
per:{
color:'#eee',
backgroundColor:'334455',
padding:[2,4],
borderRadius:3
}
}
}
},
{
name:'访问来源',
type:'pie',
radius:[0, '30%'],
data:source_stat_data,
label:{
position:'inner'
},
selectedMode:'single'
}
]
};
chart_2.setOption(option_2);
var chart_3 = echarts.init(document.getElementById('order_wrap'));
var clue_data = $:clue_data;
var clue_title = $:clue_title;
var option_3 = {
title:{
text:'销售线索转化图'
},
tooltip:{
trigger:'item',
formatter:'{a}<br/>{b}:{c}%'
},
legend:{
data:clue_title
},
toolbox:{
show:true,
feature:{
dataView:{},
restore:{},
saveAsImage:{}
}
},
series:[
{
name:'漏斗图',
type:'funnel',
data:clue_data,
label:{
position:'inner'
},
emphasis:{
label:{
fontSize:20
}
}
}
]
}
chart_3.setOption(option_3);
</script>
</body>
</html>