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

按行索引拆分DataFrame为训练/验证/测试集时遇问题

解决按行循环拆分DataFrame为训练/验证/测试集的问题

看起来你想按行的顺序依次把数据分配到训练、验证、测试集(第1条去训练,第2条去验证,第3条去测试,然后循环重复),但目前的代码有几个关键问题,我来帮你修正:

你的代码存在的问题

  • 条件逻辑错误:你用了i%2和i%3的组合,这完全不符合“依次分配”的需求,会导致数据分配混乱(比如某些行可能被同时分到多个集合,或者漏分)。
  • DataFrame.append用法错误:Pandas的append方法需要传入行数据(比如dfClimbing.iloc[i:i+1]),而且它不会原地修改DataFrame,需要重新赋值给变量;另外直接append整数i是完全错误的,你需要添加的是DataFrame的行,不是索引数字。
  • 效率低下:循环逐行添加到空DataFrame的方式在数据量大时会很慢,Pandas更推荐用批量筛选的方式。

正确的实现方式

方法1:符合你思路的循环修正版

如果你坚持用循环的方式,修正后的代码如下:

import pandas as pd

# 假设dfClimbing是你的原始DataFrame
climbingTngDataset = pd.DataFrame([])
climbingValDataset = pd.DataFrame([])
climbingTestDataset = pd.DataFrame([])

for i in range(len(dfClimbing)):
    # 按索引模3的结果分配:0→训练,1→验证,2→测试
    if i % 3 == 0:
        # 选取第i行,注意iloc[i:i+1]返回的是DataFrame,不是Series
        climbingTngDataset = pd.concat([climbingTngDataset, dfClimbing.iloc[i:i+1]], ignore_index=True)
    elif i % 3 == 1:
        climbingValDataset = pd.concat([climbingValDataset, dfClimbing.iloc[i:i+1]], ignore_index=True)
    else:
        climbingTestDataset = pd.concat([climbingTestDataset, dfClimbing.iloc[i:i+1]], ignore_index=True)

注意:Pandas已经弃用了append方法,推荐用pd.concat来合并DataFrame,而且每次合并后要重新赋值给变量,因为concat不会修改原对象。

方法2:更高效的Pandas批量筛选(推荐)

循环逐行处理效率很低,尤其是数据量大的时候,用索引筛选的方式更简洁高效:

import pandas as pd

# 生成每个行的分配标签
dfClimbing['split'] = dfClimbing.index % 3

# 批量筛选得到三个数据集
climbingTngDataset = dfClimbing[dfClimbing['split'] == 0].drop('split', axis=1).reset_index(drop=True)
climbingValDataset = dfClimbing[dfClimbing['split'] == 1].drop('split', axis=1).reset_index(drop=True)
climbingTestDataset = dfClimbing[dfClimbing['split'] == 2].drop('split', axis=1).reset_index(drop=True)

这个方法先给每行添加一个split标签(0/1/2对应训练/验证/测试),然后通过布尔索引批量筛选,最后删除临时的split列并重置索引,比循环快得多。

补充说明

如果你说的“第1条观测”是指从显示的第1行开始计数(而非默认的索引0),只需要调整标签生成逻辑即可:

# 让第1行(索引0)对应训练,第2行(索引1)对应验证,第3行(索引2)对应测试
dfClimbing['split'] = (dfClimbing.index + 1) % 3

# 对应筛选逻辑
climbingTngDataset = dfClimbing[dfClimbing['split'] == 1].drop('split', axis=1).reset_index(drop=True)
climbingValDataset = dfClimbing[dfClimbing['split'] == 2].drop('split', axis=1).reset_index(drop=True)
climbingTestDataset = dfClimbing[dfClimbing['split'] == 0].drop('split', axis=1).reset_index(drop=True)

这样就完全匹配你描述的“第1条进训练,第2条进验证,第3条进测试”的需求了。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:45:13