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

如何在Pandas中为列表类型列批量分配类别名称?

问题描述

我有一个Pandas DataFrame,其中categories列为列表类型,示例数据如下:

categories
[0, 0, 2, 2, 2]
[0, 0, 2, 2]
[0, 0, 2, 2, 2]
[1, 1, 2, 2]
[2, 2, 0, 0]
[1, 0, 2, 3]

样本列表:

li = [[0, 0, 2, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2, 2], [1, 1, 2, 2], [2, 2, 0, 0], [1, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2, 2], [0, 0, 2, 2], [2, 2, 0, 0], [2, 2, 0, 0], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [2, 2, 0, 0], [2, 2], [1, 1, 2], [0, 2, 2, 0], [0, 0, 2, 2], [0, 1], [0, 0], [0, 0, 2, 2], [0, 0], [0, 0, 2, 2], [0, 2, 2, 0], [2, 2, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [2, 2, 0, 0], [0, 0, 2, 2], [2, 2, 0, 1], [2, 2, 0, 0], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2, 2], [2, 1], [0, 0, 2, 2, 2], [2, 2, 0, 0], [2, 0], [2, 2, 0, 0], [0, 2], [0, 2, 2], [0, 0, 2, 2], [0, 2, 2, 0], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2, 2], [0, 0, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [3, 2, 0, 0], [0, 0], [0, 0, 2, 2], [0, 0, 2, 2, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [1, 3], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2], [0, 2, 0, 2], [0, 0, 2, 2], [2, 2, 0, 0], [2, 2, 0, 0], [2, 2], [0, 0, 2, 2], [0, 2], [0, 0, 2, 2], [0, 0, 2, 2], [2, 2, 0], [2, 2, 0, 0], [0, 0, 2, 2], [0, 0, 2], [2], [0, 0, 2, 2], [2, 2, 2, 1, 1], [0, 0], [0, 3], [2, 2], [1, 2], [1,3]]

需按以下优先级规则生成新列class_name:

  • 若列表中同时包含1和3,设为class1;
  • 剩余行中,若包含1,设为class2;
  • 剩余行中,若包含3,设为class3;
  • 剩余行中,若同时包含0和2,设为class4;
  • 剩余行中,若包含0,设为class5;
  • 剩余行中,若包含2,设为class6。

目前用循环实现效率很低,求无需循环的高效实现方式。

高效解决方案

可以利用Pandas的矢量化布尔索引结合集合判断实现,完全避免循环,大幅提升效率。以下是两种实现方式:

方式一:基于集合的快速判断

先将每个列表转换为集合(集合的成员判断是O(1)复杂度),再按优先级依次赋值:

import pandas as pd

# 构造DataFrame
df = pd.DataFrame({'categories': li})

# 将列表转换为集合,方便快速判断元素存在性
df['cat_set'] = df['categories'].apply(set)

# 初始化class_name列
df['class_name'] = None

# 按优先级规则赋值
# 规则1:同时包含1和3
mask = df['cat_set'].apply(lambda x: 1 in x and 3 in x)
df.loc[mask, 'class_name'] = 'class1'

# 规则2:剩余行包含1
mask = (df['class_name'].isna()) & df['cat_set'].apply(lambda x: 1 in x)
df.loc[mask, 'class_name'] = 'class2'

# 规则3:剩余行包含3
mask = (df['class_name'].isna()) & df['cat_set'].apply(lambda x: 3 in x)
df.loc[mask, 'class_name'] = 'class3'

# 规则4:剩余行同时包含0和2
mask = (df['class_name'].isna()) & df['cat_set'].apply(lambda x: 0 in x and 2 in x)
df.loc[mask, 'class_name'] = 'class4'

# 规则5:剩余行包含0
mask = (df['class_name'].isna()) & df['cat_set'].apply(lambda x: 0 in x)
df.loc[mask, 'class_name'] = 'class5'

# 规则6:剩余行包含2
mask = (df['class_name'].isna()) & df['cat_set'].apply(lambda x: 2 in x)
df.loc[mask, 'class_name'] = 'class6'

# 可选:删除临时的cat_set列
df = df.drop('cat_set', axis=1)

方式二:预提取元素存在性(更高效)

如果数据集规模极大,可以先一次性提取各目标元素的存在情况,再组合布尔条件,减少apply调用次数:

import pandas as pd

# 构造DataFrame
df = pd.DataFrame({'categories': li})

# 一次性生成各元素是否存在的布尔列
df['has_1'] = df['categories'].apply(lambda x: 1 in x)
df['has_3'] = df['categories'].apply(lambda x: 3 in x)
df['has_0'] = df['categories'].apply(lambda x: 0 in x)
df['has_2'] = df['categories'].apply(lambda x: 2 in x)

# 初始化class_name列
df['class_name'] = None

# 按优先级赋值
mask = df['has_1'] & df['has_3']
df.loc[mask, 'class_name'] = 'class1'

mask = (df['class_name'].isna()) & df['has_1']
df.loc[mask, 'class_name'] = 'class2'

mask = (df['class_name'].isna()) & df['has_3']
df.loc[mask, 'class_name'] = 'class3'

mask = (df['class_name'].isna()) & df['has_0'] & df['has_2']
df.loc[mask, 'class_name'] = 'class4'

mask = (df['class_name'].isna()) & df['has_0']
df.loc[mask, 'class_name'] = 'class5'

mask = (df['class_name'].isna()) & df['has_2']
df.loc[mask, 'class_name'] = 'class6'

# 删除临时布尔列
df = df.drop(['has_1', 'has_3', 'has_0', 'has_2'], axis=1)

这两种方式都利用了Pandas的矢量化操作,比循环快几个数量级,适合处理大规模数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 18:50:25