根据观察名称将数据拆分为训练和使用 pandas 进行测试

Posted

技术标签:

【中文标题】根据观察名称将数据拆分为训练和使用 pandas 进行测试【英文标题】:split data into training and test with pandas with respect to observation name 【发布时间】:2018-07-26 08:29:41 【问题描述】:

我想将我的数据框拆分为训练和测试数据。有一篇很棒的帖子here 介绍了如何随机执行此操作。但是,我需要根据观测值的名称对其进行拆分,以确保(例如)样本名称为“X”的 2/3 观测值分配给训练数据,样本名称为“X”的观测值的 1/3 分配给测试数据。

这是我的 DF 的顶部:

             136       137       138       139  141  143  144  145       146  \
Sample                                                                         
HC10    0.000000  0.000000  0.000000  0.000000  0.0  0.0  0.0  0.0  0.140901   
HC10    0.000000  0.000000  0.000000  0.267913  0.0  0.0  0.0  0.0  0.000000   
HC10    0.000000  0.000000  0.000000  0.000000  0.0  0.0  0.0  0.0  0.174445   
HC11    0.059915  0.212442  0.255549  0.000000  0.0  0.0  0.0  0.0  0.000000   
HC11    0.000000  0.115988  0.144056  0.070028  0.0  0.0  0.0  0.0  0.000000   

        147       148  149       150  151       152      154       156  158  \
Sample                                                                        
HC10    0.0  0.189937  0.0  0.052635  0.0  0.148751  0.00000  0.000000  0.0   
HC10    0.0  0.000000  0.0  0.267764  0.0  0.000000  0.00000  0.000000  0.0   
HC10    0.0  0.208134  0.0  0.130212  0.0  0.165507  0.00000  0.000000  0.0   
HC11    0.0  0.000000  0.0  0.000000  0.0  0.000000  0.06991  0.102209  0.0   
HC11    0.0  0.065779  0.0  0.072278  0.0  0.060815  0.00000  0.060494  0.0   

             160  173  
Sample                 
HC10    0.051911  0.0  
HC10    0.281227  0.0  
HC10    0.000000  0.0  
HC11    0.000000  0.0  
HC11    0.073956  0.0

Sample 是数据框的索引,其余是数字。

如果我使用以下解决方案:

train=df.sample(frac=0.8,random_state=200)
test=df.drop(train.index)

正如 here 所建议的那样,我的 df 中的 HC10 等样本可能都被分配给训练数据,但我将无法在它们上测试我的模型。有谁知道以这种方式对数据进行分区的快速方法(最好使用 pandas)?

非常感谢

【问题讨论】:

处理这种担忧的正常方法是使用交叉验证,即对数据的多个随机拆分进行训练和测试。 您在寻找StratifiedShuffleSplit吗? 我听说过使用交叉验证(我不是统计学家,所以不太熟悉)。那么你会建议像上面那样进行分区然后运行交叉验证吗?我会在循环中多次执行此操作并通过管道输入模型吗?还是有另一种被认为是最佳实践的方法? 【参考方案1】:

您可以按组进行抽样,以保持每个组的平衡。我会修改你的小例子:

import pandas as pd
df = pd.DataFrame(
    'group': ['a', 'a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b'], 
    'x':range(10)
)

train = df.reset_index(                  # need to keep the index as a column
    ).groupby('group'                    # split by "group"
    ).apply(lambda x: x.sample(frac=0.6) # in each group, do the random split
    ).reset_index(drop=True              # index now is group id - reset it
    ).set_index('index')                 # reset the original index
test = df.drop(train.index)              # now we can subtract it from the rest of data

另一种解决方案是使用分层抽样算法,例如来自 scikit-learn。

【讨论】:

那么这基本上是添加另一个变量来将每个观察分配给一个组,然后根据它进行分区吗? 是的,完全正确。目标是尽可能均匀地分配此变量。 在我在这里发布之前,我曾尝试过与此非常相似的东西,但问题是它不是很动态。即,如果我想像其他人提到的那样采用不同的训练/测试集进行交叉验证,那么数据集有一个固定的组标签 - 除非我错过了理解你的代码? 组标签是固定的,但可能会以不同的方式多次拆分(试试看!)。

以上是关于根据观察名称将数据拆分为训练和使用 pandas 进行测试的主要内容,如果未能解决你的问题,请参考以下文章

根据python中训练和测试集中的时间戳为每个用户拆分数据集

将 pandas 数据帧分层拆分为训练、验证和测试集

如何按百分比将 CSV 数据集拆分为训练集和测试集,并将拆分后的数据集与 pandas 一起保存到本地文件夹中? [复制]

Sklearn 将 Pandas Dataframe 和 CSR Matrix 拆分为测试和训练集

将数据拆分为训练/测试文件,以便为两个文件选择至少一个样本

Pandas - 根据日期将数据框拆分为多个数据框?