高效转换变长列表为PandasDataFrame方法
时间:2025-12-05 13:45:35 311浏览 收藏
在文章实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《变长列表高效转Pandas DataFrame技巧》,聊聊,希望可以帮助到正在努力赚钱的你。

本文旨在提供一种高效且健壮的方法,用于将具有不同长度的列表数据作为新列添加到现有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 pd
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'])
print("原始DataFrame:")
print(df)期望的结果是,将list1作为新列名,list2作为对应行的值,添加到df中,其中list2中较短的子列表应使用默认值(例如0)进行填充,以匹配list1的长度。
Name Age Gender col1 col2 col3 col4 0 Alex 33 Male 1 2 3 0 1 Marly 28 Female 2 3 0 0 2 Charlie 30 Female 1 8 4 3 3 Mimi 37 Female 22 35 32 0 4 James 44 Male 65 0 0 0 5 Jone 25 Male 2 45 55 0
传统方法的问题
一种直观但可能效率不高的方法是尝试直接将list2转换为DataFrame并赋值:
# 假设 list2 已经经过处理,使其内部子列表长度一致 # df[list1] = pd.DataFrame(list2, index=df.index)
然而,这种方法存在几个问题:
- 长度不匹配: 如果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_longest
import 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. 从字典列表创建新的 DataFrame
new_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 Gender
0 Alex 33 Male
1 Marly 28 Female
2 Charlie 30 Female
3 Mimi 37 Female
4 James 44 Male
5 Jone 25 Male
整合后的DataFrame:
Name Age Gender col1 col2 col3 col4
0 Alex 33 Male 1 2 3 0
1 Marly 28 Female 2 3 0 0
2 Charlie 30 Female 1 8 4 3
3 Mimi 37 Female 22 35 32 0
4 James 44 Male 65 0 0 0
5 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中,同时避免常见的性能陷阱,确保数据处理流程的顺畅和可靠。
理论要掌握,实操不能落!以上关于《高效转换变长列表为PandasDataFrame方法》的详细介绍,大家都掌握了吧!如果想要继续提升自己的能力,那么就来关注golang学习网公众号吧!
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
497 收藏
-
422 收藏
-
328 收藏
-
239 收藏
-
471 收藏
-
423 收藏
-
347 收藏
-
264 收藏
-
347 收藏
-
275 收藏
-
130 收藏
-
224 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习