返回介绍

使用 Pandas

发布于 2025-04-20 18:52:17 字数 6448 浏览 0 评论 0 收藏

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。