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

如何在Pandas DataFrame的列表型列中设置自定义标签

问题描述

我有一个自定义DataFrame B,其结构通过B.dtypes查看如下:

[236 rows x 10 columns]
Filename               object
Path                   object
Filenumber              int64
Channel                object
Folder                 object
User-defined labels    object
Ranking                 int64
Lower limit             int64
Upper limit             int64
Enabled                  bool
dtype: object

执行以下筛选代码:

print(
    B.loc[
        B["User-defined labels"].explode().eq("Label 1").groupby(level=0).any()
        & (B["Filenumber"] == 98)
    ]
)

得到结果:

Filename                                               Path  Filenumber      Channel   Folder User-defined labels  Ranking  Lower limit  Upper limit  Enabled
0    File_98.csv  C:\Users\test_user\Documents\Training_data\Label 1\...          98  subfolder_0  Label 1           [Label 1]        0            0       999999     True
39   File_98.csv  C:\Users\test_user\Documents\Training_data\Label 1\...          98  subfolder_1  Label 1           [Label 1]        0            0       999999     True
78   File_98.csv  C:\Users\test_user\Documents\Training_data\Label 1\...          98  subfolder_2  Label 1           [Label 1]        0            0       999999     True
117  File_98.csv  C:\Users\test_user\Documents\Training_data\Label 1\...          98  subfolder_3  Label 1           [Label 1]        0            0       999999     True

现在需要为符合条件的行的User-defined labels列替换/添加新标签,标签列表定义为:

new_labels = ["Label 1", "Label 3"]

用于定位目标行的代码如下:

B.loc[
    B["User-defined labels"].explode().eq("Label 1").groupby(level=0).any()
    & (B["Filenumber"] == 98),
    ["User-defined labels"],
]

目标行的该列初始值为[Label 1],希望修改为[Label 1, Label 3]。

已尝试的失败操作

使用loc方法尝试的操作均失败:

  • B.loc[] = new_labels,报错:Must have equal len keys and value when setting with an iterable
  • B.loc[] = [new_labels],报错:Must have equal len keys and value when setting with an ndarray
  • B.loc[] = pd.Series(new_labels, dtype=object),仅将第一行该列设为Label 1,其余列设为NaN
  • B.loc[] = pd.Series([new_labels], dtype=object),仅将第一行该列设为[Label 1, Label 3],其余列设为NaN

改用at()方法尝试同样操作,结果如下:

  • B.at[] = new_labels,报错:Must have equal len keys and value when setting with an iterable
  • B.at[] = [new_labels],报错:Must have equal len keys and value when setting with an ndarray
  • B.at[] = pd.Series(new_labels, dtype=object),报错:unhashable type: 'list'
  • B.at[] = pd.Series([new_labels], dtype=object),报错:unhashable type: 'list'
解决方案与疑问解答

1. 修改列表列的可行方法

方法一:用apply批量赋值

先把筛选条件存为变量复用:

mask = B["User-defined labels"].explode().eq("Label 1").groupby(level=0).any() & (B["Filenumber"] == 98)

直接替换目标行的标签列表:

B.loc[mask, "User-defined labels"] = B.loc[mask, "User-defined labels"].apply(lambda x: new_labels)

如果是要合并新标签并去重(而非直接替换),可以改成:

B.loc[mask, "User-defined labels"] = B.loc[mask, "User-defined labels"].apply(lambda x: list(set(x + new_labels)))

方法二:构造匹配行数的列表

loc赋值要求右侧长度与选中行数量一致,因此可以先获取目标行数,生成对应数量的标签列表:

mask = B["User-defined labels"].explode().eq("Label 1").groupby(level=0).any() & (B["Filenumber"] == 98)
row_count = B[mask].shape[0]
B.loc[mask, "User-defined labels"] = [new_labels] * row_count

2. 关于多列存储标签的疑问

你担心的三个问题确实存在:

  • 列结构更新问题:每次新增标签都要给整个DataFrame添加一列,即使多数行该标签为空,会额外占用内存,标签数量越多问题越明显。
  • 空列清理问题:删除标签时不能直接删列(会丢失其他行的标签记录),只能将对应列设为空,但空列会一直保留,后续需要遍历所有标签列检查是否全为空才能删除,操作繁琐。
  • 遍历效率问题:遍历单个列表列仅需操作一列,而多列存储需要遍历所有标签列,当标签数量较多时,前者的筛选、统计效率明显更高。

因此,继续使用列表列存储标签是更合理的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 09:45:25