python 加载xlsx文件 python数据加载_SQL


第六章 数据加载、存储与文件格式

  • 二进制格式的数据[2/2]
  • Web API交互操作[2/2]
  • 数据库交互操作[2/2]

6.2 二进制格式

Python内建的pickle序列化模块进行二进制格式化操作是存储数据(也称序列化)最高效、最方便的方式之一。pandas对象的to_pickle方法可以将数据以pickle格式写入硬盘:


In [3]: frame = pd.read_csv('examples/ex1.csv')

In [4]: frame
Out[4]:
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo

In [6]: frame.to_pickle('examples/frame_pickle')

In [7]: pd.read_pickle('examples/frame_pickle')
Out[7]:
   a   b   c   d message
0  1   2   3   4   hello
1  5   6   7   8   world
2  9  10  11  12     foo


可以直接用内建的pickle读取文件中的“pickle化”的对象,示例中更方便的使用了pandas.read_pickle进行操作。

pickle仅被推荐作为短期的存储格式。因为一个被pickle序列化的对象可能明天因为库的新版本而无法反序列化。

pandas內建支持其他两个二进制格式:HDF5和MessagePack。

pandas和numpy其他的存储格式:

  • bcolz(http://bcolz.blosc.org/),基于Blosc压缩库的可压缩列式二进制格式。
  • Feather(http://github.com/wesm/feather),R编程社区Hadley Wickham(http://hadley.nz/)设计的跨语言列式文件格式。Feather使用Apache箭头(http://arrow.apache.org)列式存储器格式。

使用HDF5格式

HDF5用于存储大量的科学数组数据,备受好评,以C库的形式提供,具有多语言接口。

HDF代表分层数据格式(Hierarchical Data Format)。

  • HDF5文件可以存储多个数据集并支持元数据。
  • 支持多种压缩模式的即时压缩,是重复模式的数据更高效的存储。
  • 适合处理不适合在内存中存储的超大型数据,可以高效读写大型数组的一小块。

通过PyTables或h5py等库可直接访问HDF5文件,但pandas提供了一个高阶的接口,可简化Series和DataFrame的存储。HDFStore类像字典一样工作并处理低级别细节:


In [8]: frame = pd.DataFrame({'a': np.random.randn(100)})

In [11]: store = pd.HDFStore('mydata.h5')

In [12]: store['obj1'] = frame

In [13]: store['obj1_col'] = frame['a']

In [14]: store
Out[14]:
<class 'pandas.io.pytables.HDFStore'>
File path: mydata.h5


包含在HDF5文件中的对象可以使用相同的字典型API进行检索:


In [16]: store['obj1']
Out[16]:
           a
0   1.834601
1  -0.825105
2   0.057644
3  -0.271681
4  -0.284001
..       ...
95  0.212565
96  0.943591
97 -0.386988
98 -0.097866
99 -0.385368

[100 rows x 1 columns]


HDFStore支持两种存储格式,‘fixed’和‘table’。后者速度更慢,但支持一种特殊语法的查询操作:


In [17]: store.put('obj2',frame, format='table')

In [18]: store.select('obj2', where=['index>=10 and index<=15'])
Out[18]:
           a
10  1.299110
11 -0.508155
12 -0.537229
13 -0.658068
14  0.650192
15 -0.434512

In [19]: store.close()


put是store['obj2']=frame方法的显式版本,但允许设置其他选项,如存储格式。

pandas.read_hdf函数是这些工具的快捷用法:


In [20]: frame.to_hdf('mydata.h5','obj3',format='table')

In [21]: pd.read_hdf('mydata.h5','obj3',where=['index < 5'])
Out[21]:
          a
0  1.834601
1 -0.825105
2  0.057644
3 -0.271681
4 -0.284001


如果处理存储在远程服务器上的数据是,比如Amazon S3或HDFS,使用其他专门为分布式存储而设计的二进制格式更为合适,比如Apache Parquet(http://parquet.apache.org)。

如果本地处理大量数据,推荐尝试PyTables和h5py,因为很多数据分析的困难在于I/O密集(而不是CPU密集),使用像HDF5这样的工具可以大大加速你的应用。

HDF5并不是数据库,它是一种适合一次写入多次读取的数据集。尽快数据可以在任何时间添加到文件中,但如果多个写入者持续写入,文件可能会损坏。

读取Excel文件

pandas支持通过ExcelFile类或pandas.read_excel函数来读写Excel2003(或更高版本)文件中的表格型数据。这是使用了xlrd和openpyxl的插件来读取xls和xlsx文件的。


In [3]: xlsx = pd.ExcelFile('examples/ex1.xlsx')

In [5]: pd.read_excel(xlsx,'Sheet1')
Out[5]:
   Unnamed: 0  a   b   c   d message
0           0  1   2   3   4   hello
1           1  5   6   7   8   world
2           2  9  10  11  12     foo


可直接将文件名传入pd.read_excel:


In [6]: frame = pd.read_excel('examples/ex1.xlsx','Sheet1')

In [7]: frame
Out[7]:
   Unnamed: 0  a   b   c   d message
0           0  1   2   3   4   hello
1           1  5   6   7   8   world
2           2  9  10  11  12     foo


pandas数据写入Excel中,首先生成一个ExcelWriter,然后使用pandas.to_excel方法写入:


In [8]: writer = pd.ExcelWriter('examples/ex2.xlsx')

In [9]: frame.to_excel(writer,'Sheet1')

In [10]: writer.save()

In [11]: frame.to_excel('examples/ex2.xlsx')  #也可以直接传入路径。


6.3 与Web API交互

简单易用的使用requests包(http://docs.python-requests.org)

如要获取GitHub上最新的30条关于pandas的问题,可以使用requests发送一个HTTP GET请求:


In [12]: import requests

In [13]: url = 'http://api.github.com/repos/pandas-dev/pandas/issues'

In [14]: resp = requests.get(url)

In [15]: resp
Out[15]: <Response [200]>


Response(响应)对象的json方法将返回一个包含解析为本地python对象的JSON的字典:


In [16]: data = resp.json()

In [17]: data[0]['title']
Out[17]: 'ENH: validate StringArray fillna value arg'


data中每个元素都是包含GitHub问题页面上的所有数据的字典(注释除外)。可以将data直接传给DataFrame,并提取感兴趣的字段:


In [19]: issues = pd.DataFrame(data,columns=['number','title','labels','state'])

In [20]: issues
Out[20]:
    number                                              title                                             labels state
0    37987         ENH: validate StringArray fillna value arg  [{'id': 42670965, 'node_id': 'MDU6TGFiZWw0MjY3...  open
1    37986  REGR: fix inplace operations for EAs with non-...  [{'id': 849023693, 'node_id': 'MDU6TGFiZWw4NDk...  open
2    37985  CLN: make MultiIndex._shallow_copy signature m...                                                 []  open
3    37984  BUG: IntervalArray.astype(categorical_dtype) l...                                                 []  open
4    37983                      CLN: remove panel compat shim  [{'id': 211029535, 'node_id': 'MDU6TGFiZWwyMTE...  open
5    37981  Deprecate inplace in Categorical.remove_catego...                                                 []  open
6    37979  Should FilePathorBuffer use os.PathLike instea...  [{'id': 1280988427, 'node_id': 'MDU6TGFiZWwxMj...  open
7    37977  BUG: CategoricalIndex.where nulling out non-ca...                                                 []  open
8    37974         BUG: fix astype conversion string -> float  [{'id': 1817503692, 'node_id': 'MDU6TGFiZWwxOD...  open
9    37972  TST: add nullable array frame constructor dtyp...  [{'id': 1465286368, 'node_id': 'MDU6TGFiZWwxND...  open
10   37971                        PERF: IntervalArray.argsort                                                 []  open
11   37967  BUG: Limited available color name list when us...  [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=...  open
12   37966                                   Read csv headers  [{'id': 47229171, 'node_id': 'MDU6TGFiZWw0NzIy...  open
13   37965  BUG: Make DTI/TDI/PI argsort match their under...  [{'id': 1741841389, 'node_id': 'MDU6TGFiZWwxNz...  open
14   37964  BUG: Bug in setitem raising ValueError when se...  [{'id': 2822098, 'node_id': 'MDU6TGFiZWwyODIyM...  open
15   37963  BUG: Some string methods treat "." as regex, o...  [{'id': 1741841389, 'node_id': 'MDU6TGFiZWwxNz...  open
16   37962                   „case-when“ function is missing?  [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=...  open
17   37957             STYLE: fail on pd.testing direct usage  [{'id': 106935113, 'node_id': 'MDU6TGFiZWwxMDY...  open
18   37956  ENH: Add argument "multiprocessing" to DataFra...  [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=...  open
19   37955  ENH: Add argument "multiprocessing" to pd.read...  [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=...  open
20   37954  BUG: df.__setitem__ can be 10x slower than pd....  [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=...  open
21   37950      ENH: 2D compat for DTA tz_localize, to_period  [{'id': 13098779, 'node_id': 'MDU6TGFiZWwxMzA5...  open
22   37949            ENH: IntervalIndex as groups in groupby  [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=...  open
23   37947  Slow autocompletion in python/ipython console ...                                                 []  open
24   37941  ENH: An argument for .query() that returns all...  [{'id': 76812, 'node_id': 'MDU6TGFiZWw3NjgxMg=...  open
25   37939  QST: how to run Pandas tests involving Numba o...  [{'id': 1954720290, 'node_id': 'MDU6TGFiZWwxOT...  open
26   37937  BUG: Concat automatically sorts index when axi...  [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=...  open
27   37935  BUG: json_normalize() upcasts column with miss...  [{'id': 76811, 'node_id': 'MDU6TGFiZWw3NjgxMQ=...  open
28   37933             ENH: make closed part of IntervalDtype  [{'id': 31404521, 'node_id': 'MDU6TGFiZWwzMTQw...  open
29   37932     BUG: loc.setitem with expansion expanding rows  [{'id': 2822098, 'node_id': 'MDU6TGFiZWwyODIyM...  open


通过复杂操作,可以创建更高阶的接口来访问常用的Web API,以返回DataFrame对象用于分析。

6.4 与数据库交互

业务场景中,大部分数据存储在基于SQL的关系型数据库中。如(SQL Server、PostgreSQL、MySQL)等。

从SQL中将数据读取为DataFreme相当简单直接,pandas多个函数可以简化这个过程。例子使用Python内建的sqlite3驱动来生成一个SQLite数据库:


In [21]: import sqlite3

In [22]: query = """
    ...: CREATE TABLE test
    ...: (a VARCHAR(20),b VARCHAR(20),
    ...: c REAL, d INTEGER);"""

In [23]: con = sqlite3.connect('mydata.sqlite')

In [24]: con.execute(query)
Out[24]: <sqlite3.Cursor at 0x13530860>

In [25]: con.commit()


再插入几行数据:


In [26]: data = [('Atlanta','Geogia',1.24,6),
    ...: ('Tallahassee','Florida',2.6,3),
    ...: ('Sacramento','California',1.7,5)]

In [27]: stmt = "INSERT INTO test VALUES(?,?,?,?)"

In [29]: con.executemany(stmt,data)
Out[29]: <sqlite3.Cursor at 0x1326e960>

In [30]: con.commit()


当从数据库的表中选择数据时,大部分Python的SQL驱动(PyODBC、psycopg2、MySQLdb、pymssql等)返回的是元组的列表:


In [31]: cursor = con.execute('select * from test')

In [32]: rows  = cursor.fetchall()

In [33]: rows
Out[33]:
[('Atlanta', 'Geogia', 1.24, 6),
 ('Tallahassee', 'Florida', 2.6, 3),
 ('Sacramento', 'California', 1.7, 5)]


可以将元组的列表传给DataFrame构造函数,但需要包含游标的description属性中的列名:


In [34]: cursor.description
Out[34]:
(('a', None, None, None, None, None, None),
 ('b', None, None, None, None, None, None),
 ('c', None, None, None, None, None, None),
 ('d', None, None, None, None, None, None))

In [35]: pd.DataFrame(rows, columns=[x[0] for x in cursor.description])
Out[35]:
             a           b     c  d
0      Atlanta      Geogia  1.24  6
1  Tallahassee     Florida  2.60  3
2   Sacramento  California  1.70  5


SQLAlchemy项目是一个流行的Python SQL工具包,抽象去除了SQL数据库之间的许多常见差异。pandas.read_sql函数允许从通用的SQLAlchemy连接中轻松地读取数据。


In [36]: import sqlalchemy as sqla

In [37]: db = sqla.create_engine('sqlite:///mydata.sqlite')

In [38]: pd.read_sql('select * from test', db)
Out[38]:
             a           b     c  d
0      Atlanta      Geogia  1.24  6
1  Tallahassee     Florida  2.60  3
2   Sacramento  California  1.70  5


- [End 2/2] -