使用 Pandas
Pandas 是一个结构化数据分析工具,它使得在 Python 中处理数据非常快速和简单。Pandas 建造在 NumPy 之上,对于 Web 开发来说使用 NumPy 的机会不多,但是在非常多的场景下都可以通过 Pandas 简化我们的工作。本节我们将展示基于 11.4 节产生的数据来做数据分析以及演示如何与 Flask 应用集成。
我们先安装它:
> pip install pandas
Pandas 入门
Pandas 包含三种数据结构。
1.Series:一维数组,与 Python 的列表类似,但 Series 中则只允许存储相同的数据类型,这样可以更有效地使用内存,提高运算效率。Series 的元素还可以自定义索引。
In : from pandas import Series In : s=Series([1, 2, 3]) In : s[1] Out : 2 In : s=Series([1, 2, 3], index=['a', 'b', 'c']) In : s.a Out : 1
2.DataFrame:二维的表格型数据结构,可以把它想象成 Excel 的工作表,它既有行索引也有列索引。
In : from pandas import DataFrame
In : data={'a':[1, 2, 3], 'b':['a', 'c', 'b'], 'c':['x', 'y', 'z']}
In : df=DataFrame(data)
In : df
Out:
a b c
0 1 a x
1 2 c y
2 3 b z
In : df.a[1]
Out: 2
In : df=DataFrame(data, index=['one', 'two', 'three'], columns=['a', 'b', 'c
'])
In : df.a.two
Out: 2
3.Panel:三维的数组,可以看作是一个三维的 DataFrame,在 Web 开发中不常用。
本节主要使用 DataFrame 这种数据类型,它提供如下常用方法。
1.把 DataFrame 对象转化成字典。
In : df.to_dict()
Out :
{'a' : {'one':1, 'three':3, 'two':2},
'b' : {'one':'a', 'three':'b', 'two':'c'},
'c' : {'one':'x', 'three':'z', 'two':'y'}}
2.行和列的对调。
In : df.T
Out :
one two three
a 1 2 3
b a c b
c x y z
3.排序。可以以轴/列来进行排序。ascending 是排序方式,默认值为 True,即降序排列:
# axis 是指用于排序的轴,可选的值有 0 和 1,默认值为 0,即按行标签(Y 轴)排
序,若为 1 则按照列标签排序
In : df.sort_index(axis=0, ascending=True)
Out:
a b c
one 1 a x
three 3 b z
two 2 c y
In : df.sort_values(by='b') # 按照列排序
Out:
a b c
one 1 a x
three 3 b z
two 2 c y
In : df.sort_values(by=['b', 'c'], ascending=[0, 1]) # 可以进行多重排序,by 和
ascending 的值的个数需要相等
Out:
a b c
two 2 c y
three 3 b z
one 1 a x
4.读写数据。DataFrame 可以方便地读写数据文件,支持 csv、Excel 和 HDF5 等类型:
In : import pandas as pd
In : csv=pd.read_csv('chapter11/section4/statistics.csv')
In : csv.head(1) # head 表示列出前 N 行,默认为 5 行
Out:
日期 周一 周二 周三 周四 周五 周六 周日
0 用户 1 34 72 38 30 75 48 75
In : csv.to_csv('new.csv') # 把内容保存到 new.csv 中
# 解析 Excel 需要预先安装 Excel 的模块 xlrd
In : xlsx=pd.read_excel('chapter11/section4/pv_uv.xlsx', 'uv', index_col=None,
na_values=['NA'])
In : xlsx.head(1)
Out:
专题页 周一 周二 周三 周四 周五 周六 周日
0 专题页 1 15509 13787 14492 14093 14008 10630 10363
# 把内容保存到 new.xlsx 中
In : xlsx.to_excel('new.xlsx', sheet_name='sheet1')
读取 MySQL 数据库
Pandas 可以方便地读取 MySQL 中的数据:
In : import MySQLdb
In : from pandas.io.sql import read_sql
In : db=MySQLdb.connect('localhost', 'web', 'web', 'r')
In : query='SELECT id, filename, filehash from PasteFile'
In : df=read_sql(query, db)
In : item=df.head(1)
In : item
Out:
id filename filehash
0 1 sample.pdf c4b19d2db0ce4530b7e92a81b52a7a63.pdf
In : item.filehash
Out:
0 c4b19d2db0ce4530b7e92a81b52a7a63.pdf
Name: filehash, dtype:object
In : item.filename.get(0) # 获得数据库对应字段的值
Out: 'sample.pdf'
我们还能把数据写进数据库。需要注意的是,con 只接受 SQLAlchemy 引擎对象和 DBAPI2(只支持 sqlite3):
In : from sqlalchemy import create_engine
In : engine=create_engine('mysql://web:web@localhost:3306/r', echo=False)
In : df.to_sql(name='new_table', con=engine, if_exists='append')
to_sql 的 if_exists 有 3 个选项。
- fail:如果表存在,则什么都不做。
- replace:如果表存在,先 drop 掉,然后重新创建,再插入数据。
- append:如果表不存在,则先创建表,否则直接插入数据。
这对开发有非常大的帮助,我们可以让数据在 csv、Excel、MySQL 之间通过 DataFrame 结构转换,非常方便。
和 Flask 应用集成
11.3 节数据报表中生成的 Excel 文件找起来很麻烦,还得翻历史邮件。如果使用 Pandas 来开发这样的应用就可以简化需求方的工作,只需要少许的 Flask 开发的经验就可以搭建一个数据报表的应用。
这个应用将提供统一格式的页面风格和访问路径,直接在 Web 页面中就可以看到数据,而且可以下载。为了减少复杂度,CSS 样式依然借助了一部分 Bootstrap 框架。
首先实现将 csv 文件转化为 DataFrame 的通用函数,传入“20160423”这样的字符串就会获得 df 对象:
def _get_frame(date_string):
if date_string is None:
date_string=date.today().strftime('%Y%M%d')
else:
try:
datetime.strptime(date_string, '%Y%M%d')
except ValueError:
return False
df=pd.read_csv(os.path.join(
CSV_DIRECTORY, '{}.csv'.format(date_string)))
return df
第一个视图用来渲染某天的 csv 数据:
@app.route('/csv/<date_string>')
def show_tables(date_string=None):
df=_get_frame(date_string)
if isinstance(df, bool) and not df: # df 对象不能直接使用“if not df”
return 'Bad date format!'
return render_template(
'chapter11/csv.html', df=df.to_html(classes='frame'), # 转化为 HTML 的同时添加
样式类
date_string=date_string)
这个视图用到的 csv 模板如下(csv.html):
<!doctype html>
<title>CSV Data</title>
<link rel=stylesheet type=text/css href="{{url_for('static', filename='stylesheets/
bootstrap.min.css')}}">
<style>
table.dataframe, .dataframe th, .dataframe td{
border:none;
border-bottom:1px solid # C8C8C8;
border-collapse:collapse;
text-align:center;
padding:10px;
margin-bottom:40px;
font-size:0.9em;
}
.frame th{
background-color:#00ccff;
color:white;
}
tr:nth-child(odd){
background-color:#eee;
}
tr:nth-child(even){
background-color:#fff;
}
tr:hover{
background-color:#aaa;
}
</style>
<div class="page">
<h1>时间:{{date_string}}</h1>
{{df|safe}}
</div>
这个模板中添加了一些 table 的样式,让 table 的奇数和偶数行的背景色不一样,这样做是为了在看数据的时候更容易集中精力。
第二个视图用于下载 csv 文件,为了演示,下载的只是从 DataFrame 对象获得的单个用户数据:
from flask import send_file
@app.route('/csv/download/<date_string>/<int:user_index>')
def serve_csv(date_string=None, user_index=None):
buffer=cStringIO.StringIO()
df=_get_frame(date_string)
if isinstance(df, bool) and not df:
return 'Bad date format!'
if user_index is not None:
df=df.loc[user_index-1] # 事实上返回的是一个 Series
df.to_csv(buffer, encoding='utf-8')
buffer.seek(0)
return send_file(
buffer, attachment_filename='{}.csv'.format(date_string),
as_attachment=True, mimetype='text/csv')
上面的视图并不会创建临时文件,而是直接在内存中读写。df.loc[index]表示只取 csv 文件中的某一行。
启动应用后,访问 http://localhost:9000/csv/20160423 就可以看到如图 11.5 所示的结果。

图 11.5 直接在 Web 页面就能看到数据
通过 http://localhost:9000/csv/download/20160423/1 可以下载 2016 年 4 月 23 日的用户 1 的数据。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论