数据的检索、加工与存储
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 as np import pandas as pd from tempfile import NamedTemporaryFile from os.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 file 11760
不出所料,.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数组挂载到根结点上
from tempfile import NamedTemporaryFile import numpy as np from os.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 in h5file.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 as np import pandas as pd from tempfile 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 as pd 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字符串