You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何高效生成基于列表笛卡尔积的Pandas DataFrame?

高效实现Pandas列表列的笛卡尔积展开

嘿,你的这个需求我太熟悉了——把每行里的列表列做笛卡尔积配对,还要给不同列标记对应的value值。原方法用Python循环逐行追加确实效率极低,尤其是数据量大的时候,因为loc[len(new_df)]每次都会触发DataFrame的内存重新分配,而且Python循环本身就远不如Pandas的矢量化操作高效。

下面给你两种高效的优化方案,全都是基于Pandas内置的矢量化操作,完全避开Python层面的循环:

方案一:用explode分步处理(直观简洁)

这是最容易理解且高效的方式,先分别处理Yes和No的配对逻辑,再合并最终结果:

import pandas as pd

# 示例数据
df = pd.DataFrame({
    'a': [[1,2,3], [7,11,6]],
    'Yes': [["a","b"], ["a","d","f"]],
    'No': [["A","B","C"], ["C","H","L","Z"]]
})

# 处理Yes部分:展开a和Yes的笛卡尔积,标记value=1
yes_df = df.explode('a').explode('Yes').rename(columns={'Yes': 'C2'})
yes_df['value'] = 1

# 处理No部分:展开a和No的笛卡尔积,标记value=0
no_df = df.explode('a').explode('No').rename(columns={'No': 'C2'})
no_df['value'] = 0

# 合并两部分并整理列名
new_df = pd.concat([yes_df[['a', 'C2', 'value']], no_df[['a', 'C2', 'value']]], ignore_index=True)
new_df = new_df.rename(columns={'a': 'C1'})

方案二:用melt+explode一次处理(更紧凑)

如果想把逻辑整合得更简洁,可以先把Yes和No列转成长格式,再一次性完成所有笛卡尔积展开:

import pandas as pd

# 示例数据
df = pd.DataFrame({
    'a': [[1,2,3], [7,11,6]],
    'Yes': [["a","b"], ["a","d","f"]],
    'No': [["A","B","C"], ["C","H","L","Z"]]
})

# 先把Yes和No转成"变量-值"的长格式
melted_df = df.melt(id_vars='a', var_name='type', value_name='C2')
# 根据type列映射对应的value值
melted_df['value'] = melted_df['type'].map({'Yes': 1, 'No': 0})
# 一次性展开a和C2的笛卡尔积,整理列名
new_df = melted_df.explode('a').explode('C2')[['a', 'C2', 'value']].rename(columns={'a': 'C1'})

为什么这两种方法更快?

  • 核心用到的explode是Pandas底层优化的矢量化操作,在C语言层面处理数据,比Python循环快几个数量级。
  • 完全避免了逐行追加new_df.loc[len(new_df)]这种低效操作,而是通过Pandas的批量操作生成结果,内存分配更高效。

你可以测试一下,不管你的DataFrame规模多大,这两种方法的速度都会比原方法快很多~

内容的提问来源于stack exchange,提问作者ImAUser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.09 15:42:58