1、二进制数据格式 实现数据的二进制格式存储最简单的办法之一是使用Python内置的pickle序列化。为了使用方便,pandas对象都有一个用于将数据以pickle形式保存到磁盘上的save方法:
In [1]: frame = pd.read_csv('ch06/ex1.csv') In [2]: frame Out[2]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo In [3]: frame.save('ch06/frame_pickle') 你可以通过另一个也很好用的pickle函数pandas.load将数据读回到Python: In [4]: pd.load('ch06/frame_pickle') 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 2、使用HDF5格式 很多工具都能实现高效读写磁盘上以二进制格式存储的科学数据。HDF5就是其中一个流行的工业级库,它是一个C库,带有许多语言接口,如Java、Python和MATLAB等。HDF5中的HDF指的是层次型数据格式(hierarchical data format)。每个HDF5文件都含有一个文件系统式的节点结构,它使你能够存储多个数据集并支持元数据。与其他简单格式相比,HDF5支持多种压缩器的即时压缩,还能更高效地存储重复模式数据。对于那些非常大的无法直接放入内存的数据集,HDF5就是不错的选择,因为它可以高效地分块读写。 Python中的HDF5库有两个接口(即PyTables和h5py),它们各自采取了不同的问题解决方式。h5py提供了一种直接而高级的HDF5 API访问接口,而PyTables则抽象了HDF5的许多细节以提供多种灵活的数据容器、表索引、查询功能以及对核外计算技术(out-of-core computation)的某些支持。 pandas有一个最小化的类似于字典的HDFStore类,它通过PyTables存储pandas对象:
In [5]: store = pd.HDFStore('mydata.h5') In [6]: store['obj1'] = frame In [7]: store['obj1_col'] = frame['a'] In [8]: store Out[8]: <class 'pandas.io.pytables.HDFStore'> File path: mydata.h5 obj1 DataFrame obj1_col Series HDF5文件中的对象可以通过与字典一样的方式进行获取: In [9]: store['obj1'] Out[9]: a b c d message 0 1 2 3 4 hello 1 5 6 7 8 world 2 9 10 11 12 foo 如果需要处理海量数据,我建议你好好研究一下PyTables和h5py,看看它们能满足你的哪些需求。由于许多数据分析问题都是IO密集型(而不是CPU密集型),利用HDF5这样的工具能显著提升应用程序的效率。 注意: HDF5不是数据库。它最适合用作“一次写多次读”的数据集。虽然数据可以在任何时候被添加到文件中,但如果同时发生多个写操作,文件就可能会被破坏。 3、读取Microsoft Excel文件 pandas的ExcelFile类支持读取存储在Excel 2003(或更高版本)中的表格型数据。由于ExcelFile用到了xlrd和openpyxl包,所以你先得安装它们才行。通过传入一个xls或xlsx文件的路径即可创建一个ExcelFile实例:
xls_file = pd.ExcelFile('data.xls') 存放在某个工作表中的数据可以通过parse读取到DataFrame中: table = xls_file.parse('Sheet1') 4、使用HTML和Web API 许多网站都有一些通过JSON或其他格式提供数据的公共API。通过Python访问这些API的办法有不少。一个简单易用的办法(推荐)是requests包(http://docs.)。为了在Twitter上搜索“python pandas”,我们可以发送一个HTTP
In [1]: import requests In [2]: url = 'http://search.twitter.com/search.json?q=python%20pandas' In [3]: resp = requests.get(url) In [4]: resp Out[4]: <Response [200]> Response对象的text属性含有GET请求的内容。许多Web API返回的都是JSON字符串,我们必须将其加载到一个Python对象中: In [5]: import json In [6]: data = json.loads(resp.text) In [7]: data.keys() Out[7]: [u'next_page', u'completed_in', u'max_id_str', u'since_id_str', u'refresh_url', u'results', u'since_id', u'results_per_page', u'query', u'max_id', u'page'] 响应结果中的results字段含有一组tweet,每条tweet被表示为一个Python字典,如下所示: {u'created_at': u'Mon, 25 Jun 2012 17:50:33 +0000', u'from_user': u'wesmckinn', u'from_user_id': 115494880, u'from_user_id_str': u'115494880', u'from_user_name': u'Wes McKinney', u'geo': None, u'id': 217313849177686018, u'id_str': u'217313849177686018', u'iso_language_code': u'pt', u'metadata': {u'result_type': u'recent'}, u'source': u'<a href="http://twitter.com/">web</a>', u'text': u'Lunchtime pandas-fu http:///SI70xZZQ #pydata', u'to_user': None, u'to_user_id': 0, u'to_user_id_str': u'0', u'to_user_name': None} 我们用一个列表定义出感兴趣的tweet字段,然后将results列表传给DataFrame:
In [8]: tweet_fields = ['created_at', 'from_user', 'id', 'text'] In [9]: tweets = DataFrame(data['results'], columns=tweet_fields) In [10]: tweets Out[10]: <class 'pandas.core.frame.DataFrame'> Int64Index: 15 entries, 0 to 14 Data columns: created_at 15 non-null values from_user 15 non-null values id 15 non-null values text 15 non-null values dtypes: int64(1), object(3) 现在,DataFrame中的每一行就有了来自一条tweet的数据: In [11]: tweets.ix[7] Out[11]: created_at Thu, 23 Jul 2012 09:54:00 +0000 from_user deblike id 227419585803059201 text pandas: powerful Python data analysis toolkit Name: 7 要想能够直接得到便于分析的DataFrame对象,只需再多费些精力创建出对常见Web API的更高级接口即可。 5、使用数据库 在许多应用中,数据很少取自文本文件,因为用这种方式存储大量数据很低效。基于SQL的关系型数据库(如SQL Server、PostgreSQL和MySQL等)使用非常广泛,此外还有一些非SQL(即所谓的NoSQL)型数据库也变得非常流行。数据库的选择通过取决于性能、数据完整性以及应用程序的伸缩性需求。 将数据从SQL加载到DataFrame的过程很简单,此外pandas还有一些能够简化该过程的函数。例如,我将使用一款嵌入式的SQLite数据库(通过Python内置的sqlite3驱动器):
import sqlite3 query = """ CREATE TABLE test (a VARCHAR(20), b VARCHAR(20), c REAL, d INTEGER );""" con = sqlite3.connect(':memory:') con.execute(query) con.commit() 然后插入几行数据:
data = [('Atlanta', 'Georgia', 1.25, 6), ('Tallahassee', 'Florida', 2.6, 3), ('Sacramento', 'California', 1.7, 5)] stmt = "INSERT INTO test VALUES(?, ?, ?, ?)" con.executemany(stmt, data) con.commit() 从表中选取数据时,大部分Python SQL驱动器(PyODBC、psycopg2、MySQLdb、pymssql等)都会返回一个元组列表: In [1]: cursor = con.execute('select * from test') In [2]: rows = cursor.fetchall() In [3]: rows Out[3]: [(u'Atlanta', u'Georgia', 1.25, 6), (u'Tallahassee', u'Florida', 2.6, 3), (u'Sacramento', u'California', 1.7, 5)] 你可以将这个元组列表传给DataFrame的构造器,但还需要列名(位于游标的description属性中): In [4]: cursor.description Out[4]: (('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 [5]: DataFrame(rows, columns=zip(*cursor.description)[0]) Out[5]: a b c d 0 Atlanta Georgia 1.25 6 1 Tallahassee Florida 2.60 3 2 Sacramento California 1.70 5 这种数据规整操作相当多,你肯定不想每查一次数据库就重写一次。pandas有一个可以简化该过程的read_frame函数(位于pandas.io.sql模块)。只需传入select语句和连接对象即可:
In [6]: import pandas.io.sql as sql In [7]: sql.read_frame('select * from test', con) Out[7]: a b c d 0 Atlanta Georgia 1.25 6 1 Tallahassee Florida 2.60 3 2 Sacramento California 1.70 5
6、存取MongoDB中的数据 NoSQL数据库有许多不同的形式。有些是简单的字典式键值对存储(如BerkeleyDB和Tokyo Cabinet),另一些则是基于文档的(其中的基本单元是字典型的对象)。本例选用的是MongoDB(http://)。我先在自己的电脑上启动一个MongoDB实例,然后用pymongo(MongoDB的官方驱动器)通过默认端口进行连接:
import pymongo con = pymongo.Connection('localhost', port=27017) 存储在MongoDB中的文档被组织在数据库的集合(collection)中。MongoDB服务器的每个运行实例可以有多个数据库,而每个数据库又可以有多个集合。假设你想保存之前通过Twitter API获取的数据。首先,我可以访问tweets集合(暂时还是空的):
tweets = con.db.tweets 然后,我将那组tweet加载进来并通过tweets.save(用于将Python字典写入MongoDB)逐个存入集合中:
import requests, json url = 'http://search.twitter.com/search.json?q=python%20pandas' data = json.loads(requests.get(url).text) for tweet in data['results']: tweets.save(tweet) 现在,如果我想从该集合中取出我自己发的tweet(如果有的话),可以用下面的代码对集合进行查询:
cursor = tweets.find({'from_user': 'wesmckinn'}) 返回的游标是一个迭代器,它可以为每个文档产生一个字典。跟之前一样,我可以将其转换为一个DataFrame。此外,还可以只获取各tweet的部分字段: tweet_fields = ['created_at', 'from_user', 'id', 'text'] result = DataFrame(list(cursor), columns=tweet_fields)
|
|