
本文旨在提供一种高效且健壮的方法,用于将具有不同长度的列表数据作为新列添加到现有pandas dataframe中,特别是在循环场景下避免dataframe碎片化带来的性能问题。通过巧妙结合使用`itertools.zip_longest`进行数据填充和`pd.concat`进行高效合并,本教程将展示如何灵活处理变长数据,确保数据整合的效率和准确性。
在数据分析和处理中,我们经常需要将新的数据列动态地添加到现有的Pandas DataFrame中。然而,当这些新数据来源于列表,并且其内部子列表长度不一致时,直接操作可能会遇到挑战,尤其是在循环中重复添加大量列时,可能导致DataFrame碎片化,从而引发性能警告甚至错误。本教程将详细介绍如何优雅地解决这一问题。
挑战:变长列表与DataFrame的整合
假设我们有以下两组数据:
list1: 包含新列的名称,例如 [‘col1’, ‘col2’, ‘col3’, ‘col4’]。list2: 包含对应新列的值,其内部子列表的长度可能不同,例如 [[1, 2, 3], [2, 3], [1, 8, 4, 3], [22, 35, 32], [65], [2, 45, 55]]。
我们还有一个初始的Pandas DataFrame df:
import pandas as pddf = 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)
期望的结果是,将list1作为新列名,list2作为对应行的值,添加到df中,其中list2中较短的子列表应使用默认值(例如0)进行填充,以匹配list1的长度。
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
传统方法的问题
一种直观但可能效率不高的方法是尝试直接将list2转换为DataFrame并赋值:
# 假设 list2 已经经过处理,使其内部子列表长度一致# df[list1] = pd.DataFrame(list2, index=df.index)
然而,这种方法存在几个问题:
西语写作助手
西语助手旗下的AI智能写作平台,支持西语语法纠错润色、论文批改写作
19 查看详情
长度不匹配: 如果list2中的子列表长度与list1的长度不一致,或者list2的行数与df的行数不一致,直接赋值会报错。性能碎片化: 更重要的是,当这种操作在循环中频繁执行,每次都添加新列时,Pandas DataFrame可能会因为内部内存重分配而变得“碎片化”,导致性能显著下降,并可能触发Performance warning DataFrame is highly fragmented警告。
为了避免这些问题,我们需要一个更健壮和高效的解决方案。
解决方案:结合itertools.zip_longest与pd.concat
该解决方案的核心思想是:
使用itertools.zip_longest对list2中的子列表进行填充,使其所有子列表的长度与所需列数(即list1的长度)保持一致。将处理后的数据转换为适合构建新DataFrame的字典列表。利用pd.concat将新生成的DataFrame与原始DataFrame进行横向合并,这是Pandas中推荐的添加多列的高效方式。
步骤详解与示例代码
首先,导入必要的库和定义初始数据:
from itertools import zip_longestimport pandas as pd# 原始数据list1 = ['col1', 'col2', 'col3', 'col4']list2 = [[1, 2, 3], [2, 3], [1, 8, 4, 3], [22, 35, 32], [65], [2, 45, 55]]df = pd.DataFrame([ ['Alex', 33, 'Male'], ['Marly', 28, 'Female'], ['Charlie', 30, 'Female'], ['Mimi', 37, 'Female'], ['James', 44, 'Male'], ['Jone', 25, 'Male']], columns=['Name', 'Age', 'Gender'])
接下来是核心处理逻辑:
# 1. 使用 zip_longest 填充 list2 中的子列表# 这一步的目的是确保 list2 中的每个子列表都具有相同的长度,# 且该长度与 list1 (列名) 的长度匹配,不足部分用 fillvalue 填充。# 具体操作:# - zip_longest(*list2, fillvalue=0) 将 list2 视为多行数据,# 进行“转置”并填充,例如 [1,2,3], [2,3] 会变成 (1,2), (2,3), (3,0)。# - 外层的 zip(*...) 再次进行“转置”,将填充后的数据恢复到# 原始的“行”结构,但现在所有行都已补齐到最大长度。# 示例:# list2_padded = [[1, 2, 3, 0], [2, 3, 0, 0], [1, 8, 4, 3], [22, 35, 32, 0], [65, 0, 0, 0], [2, 45, 55, 0]]list2_padded = list(zip(*zip_longest(*list2, fillvalue=0)))# 2. 将填充后的数据与列名 list1 结合,创建字典列表# 对于 list2_padded 中的每一行 (vals),将其与 list1 (列名) 进行 zip,# 然后转换为字典,形成 {col_name: value} 的结构。# 示例:# [{'col1': 1, 'col2': 2, 'col3': 3, 'col4': 0}, ...]new_data_dicts = [dict(zip(list1, vals)) for vals in list2_padded]# 3. 从字典列表创建新的 DataFramenew_df_cols = pd.DataFrame(new_data_dicts)# 4. 使用 pd.concat 将新旧 DataFrame 横向合并# axis=1 表示按列合并。这是添加新列的高效方式,避免了碎片化。out = pd.concat([df, new_df_cols], axis=1)print("n整合后的DataFrame:")print(out)
代码输出:
原始DataFrame: Name Age Gender0 Alex 33 Male1 Marly 28 Female2 Charlie 30 Female3 Mimi 37 Female4 James 44 Male5 Jone 25 Male整合后的DataFrame: 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
注意事项与总结
fillvalue的选择: 在zip_longest中,fillvalue参数用于填充较短序列的缺失值。根据你的数据类型和业务需求,可以选择合适的填充值(例如0、None、空字符串等)。如果新列可能包含非数值数据,则需要考虑填充值的数据类型兼容性。效率提升: 使用pd.concat是Pandas中推荐的合并DataFrame的方法,尤其是在添加多列或多行时。它通常比在循环中逐列赋值更高效,因为它会一次性构建新的DataFrame,而不是频繁地修改现有DataFrame的内存结构。这对于在循环中动态生成和添加大量列的场景尤为重要,能够有效避免性能碎片化警告。数据类型: 经过zip_longest填充后,如果fillvalue与原始数据类型不一致,新生成的DataFrame列的数据类型可能会变为更通用的类型(例如,整数和None混合可能导致对象类型)。如有需要,可以在合并后使用astype()进行类型转换。通用性: 此方法不仅适用于初始DataFrame,也适用于在循环中动态生成list1和list2的场景。每次循环迭代时,都可以使用这种方式生成新的列数据DataFrame,然后与主DataFrame进行合并,从而保持代码的简洁性和执行效率。
通过上述方法,我们可以优雅且高效地将变长列表数据整合到Pandas DataFrame中,同时避免常见的性能陷阱,确保数据处理流程的顺畅和可靠。
以上就是高效地将变长列表数据整合到Pandas DataFrame中:避免性能碎片化的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/911627.html
微信扫一扫
支付宝扫一扫