做一个Pandas专家,教你如何用它高效处理大量数据
Pandas库是Python最流行的数据操作库。它提供了一种通过数据框架api操纵数据的简便方法,灵感来自R的数据框架。
了解Pandas库
了解Pandas的关键之一是了解Panda主要是一系列其他Python库的包装器。主要是Numpy、SQLAlchemy、Matplotlib和openpyxl。
数据框架的核心内部模型是一系列numpy数组,而现在已弃用的“as_matrix”返回的Panda函数会形成内在表征。
Pandas利用其他库来获取数据帧和数据帧,例如,SQLAlchemy通过read_sql和to_sql函数使用。openpyxl和xlsx writer用于read_excel和to_excel函数。
Matplotlib和Seaborn使用诸如df.plot()之类的命令,提供了一个简单的接口来绘制数据帧中可用的信息。
Numpy的Pandas - 高效的Pandas
您经常听到的抱怨之一是Python速度慢或难以处理大量数据。通常情况下,这是由于编写的代码效率低下。确实,原生Python代码往往比编译代码慢,但像Panda这样的库可以有效地为Python代码提供编译代码的接口。让我们了解如何正确地与它进行交互,让我们充分利用Pandas / Python。
应用矢量化操作
与其底层库Numpy一样,Panda比执行循环更能有效地执行矢量化操作。这些效率是由于通过C编译代码执行的矢量化操作,而不是原生Python代码以及矢量化操作在整个数据集上操作的能力。
apply接口允许通过使用CPython接口进行循环来获得一些效率:
df.apply(lambda x: x['col_a'] * x['col_b'], axis=1)
但大多数性能增益都可以通过使用矢量化操作本身获得,无论是直接在Pandas中还是直接调用其内部Numpy数组。
从上图中可以看出,在使用矢量化操作(3.53ms)处理和使用Apply进行加法(27.8s)循环之间,性能差异可能非常大。通过直接调用numpy的数组和API可以获得额外的效率,例如:
Swifter:Swifter是一个Python库,可以很容易地在数据帧上对不同类型的操作进行矢量化,其API与Apply函数的API非常相似。
通过DTYPES高效地存储数据
当将数据帧加载到内存中时,无论是通过read_csv,还是read_excel或其他一些数据帧读取函数,SQL都会进行类型推断,这可能被证明是低效的。这些API允许您显式指定每列的类型,也允许在存储器中更有效地存储数据。
df.astype({'testColumn': str, 'testCountCol': float})
Dtypes是Numpy的原生对象,它允许您定义用于存储某些信息的确切类型和位数。
Numpy的dtype np.dtype('int32')表示一个32位长的整数。 Pandas默认为64位整数,我们可以使用32位节省一半的空间:
memory_usage()显示每列使用的字节数,因为每列只有一个条目(行),每个int64列的大小为8字节,int32为4字节。
Pandas还引入了分类dtype,它允许对频繁出现的值进行有效的内存利用。在下面的示例中,当我们将字段transition_date转换为分类值时,我们可以看到字段mailing_date的内存利用率降低了28倍。
在我们的示例中,只需更改此数据类型,数据框的总体大小就会下降3倍以上:
使用正确的dtypes不仅可以处理内存中较大的数据集,它还使一些计算变得更有效。在下面的示例中,我们可以看到使用分类类型为groupby / sum操作带来了3倍的速度提升。
在Pandas中,您可以在数据加载(read_)期间定义dtypes或作为类型转换(astype)定义dtypes。
CyberPandas:CyberPandas是不同的库扩展之一,它通过支持ipv4和ipv6数据类型,并有效地存储它们来实现更丰富的数据类型。
使用块处理大型数据集
Pandas允许通过块加载数据帧中的数据,因此可以将数据帧作为迭代器处理,并且能够处理大于可用内存的数据帧。
在读取数据源时定义chunksize和get_chunk方法的组合允许Pandas将数据作为迭代器进行处理。例如,在上面所示的示例中,数据帧每次读取2行。然后可以通过以下方式迭代这些块:
i = 0 for a in df_iter: # do some processing chunk = df_iter.get_chunk() i += 1 new_chunk = chunk.apply(lambda x: do_something(x), axis=1) new_chunk.to_csv("chunk_output_%i.csv" % i )
然后可以将其输出提供给csv文件、pickle,导出到数据库等...
通过块设置操作符还允许通过多处理来执行某些操作。
Dask:它是一个建立在Pandas之上的框架,它构建了多处理和分布式处理。它利用内存和磁盘上的Pandas数据帧集合。
SQL Alchemy的Pandas - 数据库Panda
Pandas也建立在SQLAlchemy之上,用于与数据库连接,因此它能够从不同的SQL类型的数据库下载数据集并将记录推送到数据库。使用SQLAlchemy接口(而不是使用Pandas API)直接允许我们执行Pandas本身不支持的某些操作,例如事务或upsert:
SQL 事务
Pandas还可以使用SQL事务,处理提交和回滚。Pedro Capelastegui在他的一篇博客文章中解释说,Pandas如何通过SQLAlchemy上下文管理器利用事务。
with engine.begin() as conn: df.to_sql( tableName, con=conn, ... )
如果数据加载失败,使用SQL事务的优点是事务将回滚。
SQL扩展
PandaSQL
Pandas有一些SQL扩展,例如pandasql,它允许在数据帧之上执行SQL查询。通过pandasql,可以直接查询数据框对象,就好像它们是数据库表一样。
SQL 插入
在支持此功能的数据库上,Panda本身不支持对SQL的upsert导出。 Pandas的补丁允许此功能。
MatplotLib / Seaborn - 视觉Pandas
Matplotlib和Seaborn可视化已经集成在一些数据帧API中,例如通过.plot命令。在pandas网站上有一个相当全面的文档介绍了该接口的工作原理。
扩展:存在不同的扩展,例如Bokeh和可在Jupyter笔记本中提供交互式可视化的plotly,同时还可以扩展matplotlib来处理3D图形。
其他扩展
还存在很多其他的Pandas扩展,它们可以处理非核心功能。其中一个是tqdm,它为某些操作提供了进度条功能,另一个是PrettyPandas,它允许格式化数据帧并添加摘要信息。
tqdm
tqdm是Python中与Pandas交互的进度条扩展,它允许用户在使用相关函数(progress_map和progress_apply)时查看地图的进度并对Panda数据帧应用操作:
PrettyPandas
PrettyPandas是一个库,它提供了一种简单的方法来格式化数据框并向其添加表摘要: