python - 如何对任意数量的分类变量实现分层 K 折 split ?

标签 python pandas numpy machine-learning scikit-learn

我有一个表单数据框,df:

    cat_var_1    cat_var_2     num_var_1
0    Orange       Monkey         34
1    Banana        Cat           56
2    Orange        Dog           22
3    Banana       Monkey          6
..

假设数据集中 cat_var_1 的可能值的比率为 ['Orange': 0.6, 'Banana': 0.4],cat_var_2 的可能值的比率为 ['Monkey': 0.2, 'Cat': 0.7 , '狗': 0.1].

如何将数据拆分为训练集、测试集和验证集(60:20:20 拆分),以便保留分类变量的比率?实际上,这些变量可以是任意数量,而不仅仅是两个。此外,很明显,在实践中可能永远无法实现精确的比率,但我们希望它尽可能接近。

我研究了 sklearn 中的 StratifiedKFold 方法,描述如下:how to split a dataset into training and validation set keeping ratio between classes?但这仅限于仅基于一个分类变量进行评估。

此外,如果您能提供您实现的解决方案的复杂性,我将不胜感激。

最佳答案

您可以将 df.cat_var_1+ "_"+ df.cat_var_2 传递给 StratifiedShuffleSplit.split() 的参数 y:

但是这里有一个使用DataFrame.groupby的方法:

import pandas as pd
import numpy as np

nrows = 10000
p1 = {'Orange': 0.6, 'Banana': 0.4}
p2 = {'Monkey': 0.2, 'Cat': 0.7, 'Dog': 0.1}

c1 = [key for key, val in p1.items() for i in range(int(nrows * val))]
c2 = [key for key, val in p2.items() for i in range(int(nrows * val))]
random.shuffle(c1)
random.shuffle(c2)

df = pd.DataFrame({"c1":c1, "c2":c2, "val":np.random.randint(0, 100, nrows)})

index = []
for key, idx in df.groupby(["c1", "c2"]).groups.items():
    arr = idx.values.copy()
    np.random.shuffle(arr)
    p1 = int(0.6 * len(arr))
    p2 = int(0.8 * len(arr))
    index.append(np.split(arr, [p1, p2]))

idx_train, idx_test, idx_validate = list(map(np.concatenate, zip(*index)))

关于python - 如何对任意数量的分类变量实现分层 K 折 split ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48988182/

相关文章:

python - 计算 DataFrame 中每一列的第一个非缺失值

python - 检索非 nan 值的 (index,column) 元组

python - 为什么 np.savetxt 不写任何东西?

python - 如何编写加密单元测试?

python - 需要一个 python 模块来提取文本文档

python - 让 Django 仅返回存储为 models.TextField() 的文本的前 50 个字符

python - 如何通过城市和国家获得时区?

python - 是否可以使用 python pandas 通过循环构建投资组合?

python - 在numpy中乘以对数概率矩阵的数值稳定方法

python:按特定ID计算事件