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

基于Python KNN实现对照组与测试组唯一配对及报错解决

报错原因

  • 赋值逻辑错误:iat为单个标量元素的定位方法,你右侧取到的Males_Ctrl_highEd.loc[indices[0]]是一维Series结构,无法直接赋值给单个标量位置;同时你初始化的匹配结果表行数与测试组一致,不需要固定取loc[0],应该对应第i个测试样本的行位置赋值。
  • KNN模型未随对照组更新重新拟合:你仅在循环外对初始对照组拟合了一次KNN模型,每次删除已匹配的对照样本后,对照组的索引和样本集合已经发生变化,旧模型返回的索引值已经失效,会导致匹配错误甚至索引不存在报错。

修复后可运行代码

以下是和你Matlab逻辑完全对应的Python实现:

import numpy as np
import pandas as pd
from sklearn.neighbors import NearestNeighbors

# 初始化和分段代码不变
TestGroup = pd.read_csv('KNN_DummyData1.csv', names = ['Gender', 'Age', 'Education'])
ControlGroup = pd.read_csv('KNN_DummyData2.csv', names = ['Gender', 'Age', 'Education'])

#### 按性别、教育程度分组
Males_highEd = TestGroup.loc[(TestGroup['Gender'] == 1) & (TestGroup['Education'] == 1)]
Males_highEd.reset_index(drop=True, inplace=True)
Males_highEd.drop(columns=['Gender', 'Education'], inplace=True)

Males_Ctrl_highEd = ControlGroup.loc[(ControlGroup['Gender'] == 1) & (ControlGroup['Education'] == 1)]
Males_Ctrl_highEd.reset_index(drop=True, inplace=True)
Males_Ctrl_highEd.drop(columns=['Gender', 'Education'], inplace=True)

# 匹配逻辑修改
# 初始化匹配结果表,和测试组行数一致
Matched_Males_Ctrl_highEd = pd.DataFrame().reindex_like(Males_highEd)
# 复制一份对照组避免修改原始数据
current_ctrl = Males_Ctrl_highEd.copy()

for i in range(len(Males_highEd)):
    # 每次都用当前剩余的对照组重新训练KNN
    nbrs = NearestNeighbors(n_neighbors=1, algorithm='ball_tree').fit(current_ctrl)
    distances, indices = nbrs.kneighbors(Males_highEd.iloc[i:i+1])
    # 取出匹配到的年龄值,赋值给对应行
    matched_age = current_ctrl.iloc[indices[0][0]]['Age']
    Matched_Males_Ctrl_highEd.iloc[i, Matched_Males_Ctrl_highEd.columns.get_loc('Age')] = matched_age
    print(f"{i+1} controls of {len(Males_highEd)} tests found")
    # 删除已匹配的样本,重置索引避免后续匹配错位
    current_ctrl = current_ctrl.drop(current_ctrl.index[indices[0][0]]).reset_index(drop=True)

更优方案推荐

逐个匹配的方式容易出现前面的匹配占用了全局最优样本,导致后续样本匹配偏差过大的问题,可以用*匈牙利算法(线性分配)*做全局最优匹配,保证总匹配年龄差最小,且天然满足每个对照仅被匹配一次的要求,代码更简洁、匹配效果更好:

from scipy.optimize import linear_sum_assignment

# 计算所有测试样本和对照样本的年龄差绝对值矩阵
age_diff = np.abs(Males_highEd['Age'].values.reshape(-1,1) - Males_Ctrl_highEd['Age'].values.reshape(1,-1))
# 匈牙利算法计算最优分配
row_ind, col_ind = linear_sum_assignment(age_diff)
# 直接生成匹配结果
Matched_Males_Ctrl_highEd = Males_Ctrl_highEd.iloc[col_ind].reset_index(drop=True)

内容的提问来源于stack exchange,提问作者Pi-Wi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 21:06:01