从列表移除部分元素失败:case_ids返回空列表的原因及优化方案
问题原因分析
你遇到这个问题的核心在于**case_ids的元素只有0和1两种值**,而你用了集合(set)来做差集操作:
- 当你取
case_ids[0:int(len(case_ids)*0.3)]时,这部分子列表里大概率已经包含了0和1(毕竟整个列表只有这两个值),所以set(case_ids)和set(case_ids[0:int(len(case_ids)*0.3)])其实是同一个集合{0,1}。 - 用一个集合减去它自己,结果自然是空集合,转成列表就是空的
[]。
而ids列表里的元素是1、2、3、5、6、8这类不重复的数字,前30%的元素只是其中一部分,所以set(ids) - set(前30%元素)还能剩下不少元素,看起来“正常”——但其实这个方法本身就有问题:用集合会打乱元素的顺序,还会自动去重,如果ids里有重复值的话,也会丢失信息,更关键的是你没有保持ids和case_ids的对应关系(比如某个id对应的case_id应该一起进入训练集或测试集)。
更优的实现方法
你的真实需求应该是把成对的ids和case_ids按相同的样本拆分,分成训练集和测试集,同时保持两者的对应关系。这里推荐两种靠谱的方法:
方法1:用随机索引拆分(基础版)
利用random模块生成随机的索引,确保两个列表按相同的索引拆分:
import random # 先获取所有样本的索引 indices = list(range(len(ids))) # 随机打乱索引顺序 random.shuffle(indices) # 计算训练集和测试集的拆分点(70%训练,30%测试) split_point = int(len(indices) * 0.7) # 根据打乱后的索引拆分两个列表 training_indices = indices[:split_point] testing_indices = indices[split_point:] trainingids = [ids[i] for i in training_indices] trainingcase_ids = [case_ids[i] for i in training_indices] testingids = [ids[i] for i in testing_indices] testingcase_ids = [case_ids[i] for i in testing_indices]
这个方法的优势:
- 完全保留
ids和case_ids的一一对应关系 - 随机拆分避免了原列表顺序带来的偏差,更符合训练集/测试集的拆分逻辑
- 不会丢失原列表的重复元素或打乱元素本身
方法2:用sklearn工具拆分(专业版,适合机器学习场景)
如果是机器学习项目,直接用sklearn的train_test_split工具,一步到位:
from sklearn.model_selection import train_test_split # 按30%的比例拆分测试集,random_state固定随机种子保证结果可复现 trainingids, testingids, trainingcase_ids, testingcase_ids = train_test_split( ids, case_ids, test_size=0.3, random_state=42 )
这个方法更简洁,还支持设置随机种子(random_state),方便你复现实验结果,适合需要严谨验证的场景。
额外提醒
- 绝对不要用集合处理这类需要保持对应关系的列表拆分:集合会丢失元素顺序、自动去重,直接破坏样本的配对关系
- 如果
ids是样本的唯一标识,拆分时必须保证每个id对应的case_id同步进入训练集或测试集,否则会导致样本数据不匹配
内容的提问来源于stack exchange,提问作者newtothis
相关产品推荐
相关产品推荐

