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

如何为DataFrame各ID统计与其他ID的1-6项共享物品数量?

问题描述

我有一个如下所示的DataFrame,其中每个id对应3至6个物品(item):

id  item_1      item_2      item_3      item_4      item_5      item_6
1   13103802    13060661    13339404    12896842    13308823    NA
2   448361      497992      13103802*   13002842    NA          NA
3   13031560    13103802*   13268709    2139908     1954965     12930979    
4   13060661*   13339404*   446881      13406902    NA          NA
5   12980231    12980231    12980231    NA          NA          NA
6   12896842*   13339404*   12717215    444032      13308823*   NA  
7   2098716     449342      13339070    12993196    2649922     NA  
8   2678151     12700906    12903744    2623298     12736032    349511  
9   2501765     2534504     2629353     NA          NA          NA  
10  12955428    12766447    12944593    NA          NA          NA

需要为每个id统计其他id中与它共享至少1个、2个……最多6个物品的数量,最终在DataFrame中新增6列,分别对应1 item、2 items……6 items的其他id数量。例如id1的1 item列值为4(与id2、3、4、6共享至少1个物品),2 items列值为2(与id4、6共享至少2个物品),3 items列值为1(与id6共享至少3个物品)。

解决方案

方法1:基础循环实现(适合小数据集)

步骤1:预处理物品数据

先统一物品格式(去掉末尾的*),并将每个id的物品转换为集合,方便后续计算交集:

import pandas as pd

# 假设数据已加载到df中,也可以直接构造数据
# df = pd.read_csv("your_data_file.csv")

# 定义处理函数:提取每个id的有效物品,转为集合
def get_item_set(row):
    # 遍历item列,去掉*、过滤NA,转为字符串避免类型冲突
    items = [str(x).rstrip('*') for x in row[1:] if pd.notna(x)]
    return set(items)

# 新增item_set列存储每个id的物品集合
df['item_set'] = df.apply(get_item_set, axis=1)

步骤2:统计共享物品数量

遍历每个id,和其他id计算物品交集大小,再统计满足不同阈值的id数量:

# 定义新增列的名称
stat_cols = [f"{k} item{'s' if k>1 else ''}" for k in range(1, 7)]

# 初始化统计结果
stats = {col: [] for col in stat_cols}

for _, current_row in df.iterrows():
    current_items = current_row['item_set']
    # 初始化1-6个共享物品的计数
    count_list = [0]*6
    
    # 遍历其他所有id
    for _, other_row in df.iterrows():
        if current_row['id'] == other_row['id']:
            continue  # 跳过自身
        other_items = other_row['item_set']
        # 计算共享物品数量
        common_count = len(current_items & other_items)
        
        # 对每个阈值k,只要共享数>=k就计数+1
        for k_idx in range(6):
            if common_count >= (k_idx + 1):
                count_list[k_idx] += 1
    
    # 将当前id的统计结果存入字典
    for col, cnt in zip(stat_cols, count_list):
        stats[col].append(cnt)

# 将统计结果合并到原DataFrame
df = pd.concat([df, pd.DataFrame(stats)], axis=1)

方法2:矩阵化优化(适合大数据集)

如果数据量较大,循环效率偏低,可以用矩阵乘法实现更高效的计算:

# 提取所有唯一物品
all_unique_items = set()
for item_set in df['item_set']:
    all_unique_items.update(item_set)
all_unique_items = list(all_unique_items)

# 构造物品存在矩阵:行是id,列是物品,值为1表示该id拥有该物品
item_matrix = pd.DataFrame(0, index=df['id'], columns=all_unique_items)
for _, row in df.iterrows():
    item_matrix.loc[row['id'], list(row['item_set'])] = 1

# 矩阵乘法得到两两id的共享物品数矩阵
common_count_matrix = item_matrix @ item_matrix.T

# 统计每个id满足>=k的其他id数量(减去自身的1)
for k in range(1, 7):
    col_name = f"{k} item{'s' if k>1 else ''}"
    df[col_name] = (common_count_matrix >= k).sum(axis=1) - 1

结果说明

执行完上述代码后,原DataFrame会新增6列,分别对应每个id与其他id共享至少1到6个物品的数量。以id1为例,结果会和示例一致:1 item=4,2 items=2,3 items=1,4 items及以后的列值为0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:44:55