数据的检索、加工与存储

1.利用Numpy和pandas对CSV文件进行写操作

对CSV文件进行写操作,numpy的savetxt()函数是与loadtxt()相对应的一个函数,他能以诸如CSV之类的区隔型文件格式保存数组:

np.savetxt('np.csv',a,fmt='%.2f',delimiter=',',header="#1,#2,#3,#4")

上面的函数调用中,我们规定了用以保存数组的文件的名称、数组、可选格式、间隔符(默认为空格符)和一个可选的标题。

利用随机数组来创建pandas DataFrame,如下:

df=pd.DataFrame(a)

利用pandas的to_csv()方法可以为CSV文件生成一个DataFrame

df.to_csv('pd.csv',float_format='%.2f',na_rep="NAN!")

对于这个方法,我们需要提供文件名、类似于Numpy的savetxt()函数的格式化参数的可选格式串和一个表示NaN的可选字符串

2.Numpy.npy与pandas DataFrame

大部分情况下,用CSV格式来保存文件是不错的主意,因为大部分程序设计语言和应用程序都能处理这种格式,所以交流起来非常方便。然而,这种格式有一个缺陷,就是它的存储效率不是很高,原因是CSV及其他纯文本格式中含有大量空白符;而后来发明的一些文件格式,如zip、bzip和gzip等,压缩率则有了显著提升。

import numpy asnp

import pandasaspdfromtempfile import NamedTemporaryFilefromos.path import getsize

np.random.seed(42)

a=np.random.randn(365,4)

tmpf=NamedTemporaryFile()

np.savetxt(tmpf,a,delimiter=',')

print("Size CSV file",getsize(tmpf.name))

tmpf=NamedTemporaryFile()

np.save(tmpf,a)

tmpf.seek(0)

loaded=np.load(tmpf)

print("shape",loaded.shape)

print("Size .npy file",getsize(tmpf.name))

df=pd.DataFrame(a)

df.to_pickle(tmpf.name)

print("Size pickled dataframe",getsize(tmpf.name))

print("DF from pickle\n",pd.read_pickle(tmpf.name))

Numpy为自己提供了一种专用的格式,称为.女朋友,可以用于存储Numpy数组。在进一步说明这种格式之前,我们先来生成一个365×4d的Numpy数组,并给各个元素填充上随机值。这个数组可以看成是一年中4个随机变量的每日观测值的模拟。这里我们使用Python标准的NamedTemporaryFile来存储数据,这些临时文件随后会自动删除。

下面将该数组存入一个CSV文件,并检查其大小,代码如下:

tmpf=NamedTemporaryFile()

np.savetxt(tmpf,a,delimiter=',')

print("Size CSV file",getsize(tmpf.name))

下面首先以Numpy.npy格式来保存该数组,随后载入内存,并检查数组的形状以及该.npy文件的大小,具体代码如下所示:

tmpf=NamedTemporaryFile()

np.save(tmpf,a)

tmpf.seek(0)

loaded=np.load(tmpf)

print("shape",loaded.shape)

print("Size .npy file",getsize(tmpf.name))

为了模拟该临时文件的关闭与重新打开过程,我们在上面的代码中调用了seek()函数。数组的形状以及文件大小如下所示:

Shape(365,4)

Size .npy file11760

不出所料,.npy文件的大小只有CSV文件的1/3左右。实际上,利用Python可以存储任意复杂的数据结构。也可以序列化格式来存储pandas的DataFrame或者Series数据结构。

提示:

在Python中,pickle是将Python对象存储到磁盘或其他介质时采用的一种格式,这个格式化的过程叫做序列化(pickling).之后,我们可以从存储器中重建该Python对象,这个逆过程称为反序列化(unpickling).

首先用前面生成的Numpy数组创建一个DataFrame,接着用to_pickle()方法将其写入一个pickle对象中,然后用read_pickle()函数从这个pickle对象中检索该DataFrame:

df=pd.DataFrame(a)

df.to_pickle(tmpf.name)

print("Size pickled dataframe",getsize(tmpf.name))

print("DF from pickle\n",pd.read_pickle(tmpf.name))

该DataFrame经过序列化后,尺寸略大于.npy文件。

3.使用PyTables 存储数据

层次数据格式(HDF)是一种存储大型数值数据的技术规范,起源于超级计算社区,目前已经成为一种开放的标准。这里用HDF5,该版本仅仅通过组(group)和数据集(dataset)这两种基本结构来组织数据。数据集可以是同类型的多维数组,而组可以用来存放其他组或者数据集。这里的“组”跟层次式文件系统中的“目录”非常像。

HDF5最常见的两个主要Python程序库是:

1.h5y

2.PyTables

本例中使用的是PyTables。不过,这个程序库需要用到一些依赖项,比如:

1.Numpy

2.numexpr:该程序包在计算包含多种运算的数组表达式时,其速度要比Numpy快许多倍

3.HDF5:如果使用HDF5的并行版本,则还需要安装MPI.

据Numexpr自称,它在某些方面的运算速度要比Numpy快得多,因为它支持多线程,并且自己得虚拟机是C语言实现得。

此外,我们需要生成一些随机数,并用它们来给一个Numpy数组赋值。下面创建一个HDF5文件,并把这个Numpy数组挂载到根结点上

fromtempfile import NamedTemporaryFile

import numpyasnpfromos.path import getsize

a=np.random.randn(365,4)

tmpf=NamedTemporaryFile()

h5file=tables.openfile(tmpf.name,mode='w',title="Numpy Array")

root=h5file.root

h5file.createArray(root,"array",a)

h5file.close()

#读取这个HDF5,并显示文件大小

h5file=tables.openfile(tmpf.name,"r")

print(getsize(tmpf.name))

通过遍历取为里面的数据

for node inh5file.iterNodes(h5file.root):

b=node.read()

print(type(b),b.shape)

4.Pandas DataFrame与HDF5仓库之间的读写操作

HDFStore类可以看作是pandas中负责HDF5数据处理部分的一种抽象。借助一些随机数据和临时文件,可以很好地展示这个类地功能特性,具体步骤如下所示:

将临时文件地路径传递给HDFStore的构造函数,然后创建一个仓库:

store=pd.io.pytables.HDFStore(tmpf.name)

print(store)

上述代码将打印输出该仓库的文件路径及其内容,不过,此刻他还没有任何内容。

HDFStore提供了一个类似字典类型的接口,如我们可以通过pandas中DataFrame的查询键来存储数值。为了将包含随机数据的一个DataFrame存储到HDFStore中,可以使用下列代码:

store['df']=df

print(store)

我们可以用三种方式来访问DataFrame,分别是:使用get()方法访问数据,利用类似字典的查询键访问数据,或者使用点运算符号来访问数据:

print("Get",store.get('df').shape)

print("Lookup",store['df'].shape)

print("Dotted",store.df.shape)

该DataFrame的形状同样也可以通过3种不同的方式进行访问

为了删除仓库中的数据,我们既可以使用remove()方法,也可以使用del运算符。当然,每个数据只能删除一次。

del store['df']

属性 is_open的作用是指出仓库是否处于打开状态。为了关闭一个仓库,可以调用close()方法。下面代码展示关闭仓库的方法,并针对仓库的状态进行了相应的检查:

print("Before close",store.is_open)

store.close()

print("After close",store.is_open)

为读写HDF数据,pandas还提供了两种方法:一种是DataFrame的to_hdf()方法;另一种是顶级的read_hdf()函数。

df.to_hdf(tmpf.name,'data',format='table')

print(pd.read_hdf(tmpf.name,'data',where=['index>363']))

用于读写操作的应用程序接口的参数包括:文件路径、仓库中组的标识符以及可选的格式串。这里的格式有两种:一种是固定格式;一种是表格格式。固定格式的优点是速度要更快一些,缺点是无法追加数据,也不能进行搜索。表格格式相当于PyTables的Table结构,可以对数据进行搜索和选择操作。

5.使用pandas读写Excel文件

现实中许多重要数据都是以Excel文件的形式存放的。当然,如果需要,也可以将其转换为可移植性更高的诸如CSV之类的格式。不过,利用Python来操作Excel文件会更加方便。在Python的世界里,为实现同一目标的项目通常不止一个,如提供Excel I/O操作功能的项目就是如此。只要安装了这些模块,就能让pandas具备读写Excel文件的能力,只是这些方面的说明文档不是很完备,其原因是pandas依赖的这些项目往往各自为战,并且发展极为迅猛。这些pandas程序包对于Excel文件也很挑剔,要求这些文件的后缀必须是.xls或者.xlsx;否则会报错。

模块openpyxl源于PHPExcel,它提供了针对.xlsx文件的读写功能。

模块xlsxwriter也需要读取.xlsx文件

模块xlrd能用来析取.xls和.xlsx文件中的数据。下面,我们先来生成用于填充pandas中DataFrame的随机数,然后用这个DataFrame创建一个Excel文件,接着再用Excel文件重建DataFrame,并通过mean()方法来计算其平均值。对于Excel文件的工作表,我们既可以为其指定一个从0开始计数的索引,也可以为其规定一个名称

import numpy asnp

import pandasaspdfromtempfile import NamedTemporaryFile

np.random.seed(42)

a=np.random.randn(365,4)

tmpf=NamedTemporaryFile(suffix='.xlsx')

df=pd.DataFrame(a)

print(tmpf.name)

df.to_excel(tmpf.name,sheet_name='Random Data')

print("Means\n",pd.read_excel(tmpf.name,'Random Data').mean())

通过to_excel()方法创建Excel文件,有用顶级read_excel()函数来重建DataFrame

6.使用pandas读写JSON

pandas提供的read_json()函数,可以用来创建pandas Series或者pandas DataFrame数据结构。

import pandas aspd

json_str='{"country":"Netherlands","dma_code":"0","timezone":"Europe\/Amsterdam","area_code":"0","ip":"46.19.37.108","asn":"AS196752","continent_code":"EU","isp":"Tilaa V.O.F.","longitude":5.75,"latitude":52.5,"country_code":"NL","country_code3":"NLD"}'data=pd.read_json(json_str,typ='series')

print("Series\n",data)

data["country"]="Brazil"print("New Series\n",data.to_json())

调用read_json()函数时,既可以向其传递一个JSON字符串,也可以为其指定一个JSON文件的路径。上面的例子中,我们是利用JSON字符串来创建pandas Series

并且再次修改country的值,并用to_json()方法将其从pandas Series转换为JSON字符串