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

基于重复ID的DataFrame Labels列填充:Pandas高效实现方案

更优雅高效的Pandas实现方案

问题背景

现有两个Pandas DataFrame:df1和df2,示例代码如下:

import pandas as pd
import numpy as np  # 补充原代码缺失的导入

col_1= ["A", ["B","C"], ["A","C","D"], "D"]
col_id = [1,2,3,4]
col_2 = [1,2,2,3,3,4,4]
d1  = {'ID': [1,2,3,4], 'Labels': col_1}
d2  = {'ID': col_2, }
d_2_get = {'ID': col_2, "Labels": ["A", "B", "C", "A", "C", "D", np.nan] }
df1 = pd.DataFrame(data=d1)
df2 = pd.DataFrame(data=d2)
df_2_get = pd.DataFrame(data=d_2_get)

df1的Labels列包含单个值或列表,df2的ID列存在重复条目。需要给df2添加Labels列,规则如下:

  • 按df2的行顺序,对应ID从df1的Labels中取第一个值
  • 若df2中ID重复,则取下一个可用值,无可用值时填充NaN

预期输出为df_2_get:

ID  Labels
0   1   A
1   2   B
2   2   C
3   3   A
4   3   C
5   4   D
6   4   NaN

现有实现

当前已有初步实现代码:

from collections import Counter
import numpy as np  # 补充缺失导入

def list_flattener(list_of_lists):
    return [item for row in list_of_lists for item in row]

def my_dataframe_filler(df1, df2):
    list_2_fill = []
    repeats = dict(Counter(df2["ID"]))
    for k in repeats.keys():
        available_labels_list = df1[df1["ID"]==k]["Labels"].tolist()
        available_labels_list+=[[np.nan]*10]
        available_labels_list = list_flattener(available_labels_list)
        list_2_fill+=available_labels_list[:repeats[k]]
    return list_2_fill

使用方式:

df2["Labels"] = my_dataframe_filler(df1, df2)

优化实现方案

下面是更贴合Pandas风格、高效简洁的实现方法,避免手动循环计数,利用Pandas内置的分组、映射特性完成需求:

简洁版实现代码

import pandas as pd
import numpy as np

# 先统一处理df1的Labels列,确保都是列表格式后展开
df1_processed = df1.assign(
    Labels=df1['Labels'].apply(lambda x: x if isinstance(x, list) else [x])
).explode('Labels')

# 统计df2中每个ID的出现次数,生成对应长度的标签列表(不足补NaN)
label_map = {}
for id_val, cnt in df2['ID'].value_counts().sort_index().items():
    id_labels = list(df1_processed[df1_processed['ID'] == id_val]['Labels'])
    # 补充NaN到所需长度
    label_map[id_val] = id_labels + [np.nan] * (cnt - len(id_labels))

# 按df2的行顺序依次取出对应标签
df2['Labels'] = [label_map[id_val].pop(0) for id_val in df2['ID']]

# 查看结果
print(df2)

更贴合Pandas原生API的版本

import pandas as pd
import numpy as np

# 处理df1:展开Labels并添加组内序号
df1_expanded = df1.assign(
    Labels=df1['Labels'].apply(lambda x: x if isinstance(x, list) else [x])
).explode('Labels').assign(
    seq=lambda x: x.groupby('ID').cumcount()
)

# 处理df2:添加组内序号
df2_with_seq = df2.assign(
    seq=lambda x: x.groupby('ID').cumcount()
)

# 匹配并填充Labels,最后恢复原顺序
result = df2_with_seq.merge(
    df1_expanded, on=['ID', 'seq'], how='left'
).drop(columns='seq').sort_index()

print(result)

这两个版本均避免了手动遍历计数,利用Pandas的向量化操作提升效率,代码结构更清晰易读,符合Pandas的原生使用风格。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:52:10