计算1+2+3+4+5+6...+100用python_利用Python进行数据分析——数据加载、存储与文件格式(六)(3) | 学步园...

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]:

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.python-requests.org)。为了在Twitter上搜索“python pandas”,我们可以发送一个HTTP

GET请求,如下所示:

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对象的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'web',

u'text': u'Lunchtime pandas-fu http://t.co/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]:

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.org)。我先在自己的电脑上启动一个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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值