
本文详细阐述了如何高效且优雅地将外部变长列表数据作为新列添加到现有Pandas DataFrame中,同时避免因频繁操作或数据长度不一致导致的性能碎片化警告。通过结合Python的`itertools.zip_longest`函数处理数据对齐与填充,并利用Pandas的`pd.concat`进行一次性合并,本教程提供了一种在处理动态或迭代数据添加场景下的优化策略,确保数据处理的效率和稳定性。
在数据分析和处理中,我们经常需要将外部数据源集成到现有的Pandas DataFrame中。一个常见的挑战是,当需要添加的数据以列表形式存在,并且这些列表的长度可能不一致时。更复杂的是,当这种添加操作需要在循环中重复执行,或者涉及大量列时,不当的处理方式可能导致显著的性能问题,例如Pandas发出的“DataFrame is highly fragmented”(DataFrame高度碎片化)警告。本教程将介绍一种健壮且高效的方法来解决这一问题。
核心挑战:变长数据与性能优化
考虑以下场景:我们有一个列名列表(list1)和一个包含多个子列表的列表(list2),其中每个子列表代表一行数据,且它们的长度可能不同。我们的目标是将list1中的元素作为新的列名,list2中的数据填充到这些新列中,并与现有DataFrame的行对齐,对于缺失的数据点(由于子列表长度不足)填充一个默认值(例如0)。
直接使用类似df[list1] = pd.DataFrame(list2, index=df.index)的方式,虽然在某些简单情况下可行,但当list2中的子列表长度不一致时,会遇到数据对齐问题。更重要的是,在循环中反复对DataFrame进行列的增删改查操作,会导致DataFrame的内存布局变得碎片化,从而降低后续操作的性能。
解决方案:结合itertools.zip_longest与Pandas
为了高效地解决上述问题,我们将利用Python标准库中的itertools.zip_longest函数来处理变长列表的对齐和填充,然后通过构建一个完整的临时DataFrame并使用pd.concat进行一次性合并,从而避免性能碎片化。
示例数据准备
首先,我们定义初始的列名列表、数据列表和现有的DataFrame:
import pandas as pdfrom itertools import zip_longest# 列名列表list1 = ['col1', 'col2', 'col3', 'col4']# 变长数据列表list2 = [[1, 2, 3], [2, 3], [1, 8, 4, 3], [22, 35, 32], [65], [2, 45, 55]]# 现有DataFramedf = pd.DataFrame([ ['Alex', 33, 'Male'], ['Marly', 28, 'Female'], ['Charlie', 30, 'Female'], ['Mimi', 37, 'Female'], ['James', 44, 'Male'], ['Jone', 25, 'Male']], columns=['Name', 'Age', 'Gender'])print("原始DataFrame:")print(df)
原始DataFrame df 如下:
Name Age Gender0 Alex 33 Male1 Marly 28 Female2 Charlie 30 Female3 Mimi 37 Female4 James 44 Male5 Jone 25 Male
步骤一:处理变长列表数据并填充
itertools.zip_longest是处理多个可迭代对象时,当它们长度不一致时进行填充的强大工具。在这里,我们将利用它来确保list2中的每个子列表都被填充到与list1相同(或至少是list2中最长子列表)的长度。
核心思想是使用zip(*zip_longest(*list2, fillvalue=0))这个模式。让我们逐步解析:
*list2:将list2解包,使其子列表作为独立的参数传递给zip_longest。zip_longest(*list2, fillvalue=0):这会像转置一样处理list2。它会从每个子列表中取出对应位置的元素,形成新的元组,如果某个子列表的元素不足,则用fillvalue(这里是0)填充。例如,对于[[1,2,3], [2,3]],它会生成(1,2), (2,3), (3,0)。zip(*…):再次使用zip和解包操作,将上一步生成的元组序列再次转置回来。这次转置的结果是,list2中的每个原始子列表都将被填充到其在list2中最长子列表的长度。例如,从(1,2), (2,3), (3,0)转置回来,会得到(1,2,3), (2,3,0)。
# 使用itertools.zip_longest处理变长列表,并填充缺失值# zip(*zip_longest(*list2, fillvalue=0)) 的作用是:# 1. zip_longest(*list2, fillvalue=0) 先将list2进行“转置”,同时用fillvalue填充短的子列表# 例如:list2 = [[1,2,3], [2,3]] -> (1,2), (2,3), (3,0)# 2. 外层的 zip(*...) 再将结果“转置”回来,此时每个原始子列表都被填充到了最长子列表的长度# 例如:(1,2), (2,3), (3,0) -> (1,2,3), (2,3,0)padded_data_rows = [ dict(zip(list1, vals)) for vals in zip(*zip_longest(*list2, fillvalue=0))]# 将处理后的数据转换为新的DataFramenew_cols_df = pd.DataFrame(padded_data_rows)print("n新生成列的DataFrame:")print(new_cols_df)
new_cols_df 的输出将是:
col1 col2 col3 col40 1 2 3 01 2 3 0 02 1 8 4 33 22 35 32 04 65 0 0 05 2 45 55 0
可以看到,list2中的每个子列表都已根据list1的长度(或list2中最长子列表的长度)进行了填充,缺失值用0表示。
步骤二:合并DataFrame
最后一步是将原始DataFrame df 与新生成的列DataFrame new_cols_df 进行合并。我们使用pd.concat函数,并指定axis=1表示按列合并。
# 使用pd.concat将原始DataFrame与新列DataFrame合并out_df = pd.concat([df, new_cols_df], axis=1)print("n最终合并后的DataFrame:")print(out_df)
最终的DataFrame out_df 如下:
Name Age Gender col1 col2 col3 col40 Alex 33 Male 1 2 3 01 Marly 28 Female 2 3 0 02 Charlie 30 Female 1 8 4 33 Mimi 37 Female 22 35 32 04 James 44 Male 65 0 0 05 Jone 25 Male 2 45 55 0
这正是我们期望的结果。
性能考量与最佳实践
避免碎片化警告:通过一次性构建新的DataFrame (new_cols_df),然后使用pd.concat进行一次性合并,我们避免了对原始DataFrame进行多次原地修改。这种方法在内存管理上更高效,能有效避免“DataFrame is highly fragmented”的性能警告,尤其是在处理大型数据集或在循环中添加数据时。循环中的应用:即使在循环中,如果每次迭代都会生成新的list1和list2,也推荐在每次迭代中按照上述方法构建临时的new_cols_df。如果需要在循环外部进行最终合并,可以考虑将每次迭代生成的new_cols_df存储在一个列表中,然后在循环结束后使用pd.concat一次性合并所有这些新的DataFrame。fillvalue的选择:zip_longest的fillvalue参数非常灵活,可以根据业务需求设置为0、None、np.nan(需要导入NumPy)或其他任何合适的值。列名与数据长度匹配:请注意,dict(zip(list1, vals))会根据list1的长度来创建字典键。如果list1的长度小于vals(即list2中最长子列表)的长度,那么vals中多余的数据将会被截断。反之,如果list1的长度大于vals的长度,那么多余的列名在字典中将没有对应值,默认会创建NaN或None值(取决于pd.DataFrame的构造方式),这需要根据实际情况进行调整。在我们的例子中,list1的长度恰好等于list2中最长子列表的长度,所以没有出现截断或额外的NaN列。
总结
本教程提供了一种在Pandas中高效处理变长列表数据并将其作为新列添加到DataFrame的专业方法。通过巧妙地结合itertools.zip_longest进行数据对齐和填充,并利用pd.DataFrame和pd.concat进行批处理式合并,我们不仅解决了数据长度不一致的问题,还显著提升了性能,避免了常见的DataFrame碎片化警告。这种方法尤其适用于需要动态生成和集成数据到DataFrame的复杂场景。
以上就是高效集成变长列表数据至Pandas DataFrame:避免性能碎片化的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1380802.html
微信扫一扫
支付宝扫一扫