使用 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 的数据。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论