web-dev-qa-db-fra.com

Fractionnement stratifié de pandas trame de données dans la formation, la validation et l'ensemble de tests

Le DataFrame extrêmement simplifié suivant représente un DataFrame beaucoup plus grand contenant des diagnostics médicaux:

medicalData = pd.DataFrame({'diagnosis':['positive','positive','negative','negative','positive','negative','negative','negative','negative','negative']})
medicalData

    diagnosis
0   positive
1   positive
2   negative
3   negative
4   positive
5   negative
6   negative
7   negative
8   negative
9   negative

Pour l'apprentissage automatique, je dois diviser au hasard cette trame de données en trois sous-trames de la manière suivante:

trainingDF, validationDF, testDF = SplitData(medicalData,fractions = [0.6,0.2,0.2])

Lorsque le tableau fractionné spécifie la fraction des données complètes qui va dans chaque sous-trame, les données dans le sous-cadre doivent s'exclure mutuellement et le tableau divisé doit être égal à un. De plus, la fraction des diagnostics positifs dans chaque sous-ensemble doit être approximativement la même.

Réponses à cette question recommande d'utiliser la méthode exemple pandas ou la fonction train_test_split de sklearn . Mais aucun des ces solutions semblent bien généraliser à n divisions et aucune ne fournit une division stratifiée.

7
user1934212

np.array_split

Si vous souhaitez généraliser en n splits, np.array_split est votre ami (cela fonctionne bien avec DataFrames).

fractions = np.array([0.6, 0.2, 0.2])
# shuffle your input
df = df.sample(frac=1) 
# split into 3 parts
train, val, test = np.array_split(
    df, (fractions[:-1].cumsum() * len(df)).astype(int))

train_test_split

Une solution venteuse utilisant train_test_split pour le fractionnement stratifié.

y = df.pop('diagnosis').to_frame()
X = df
X_train, X_test, y_train, y_test = train_test_split(
        X, y,stratify=y, test_size=0.4)

X_test, X_val, y_test, y_val = train_test_split(
        X_test, y_test, stratify=y_test, test_size=0.5)

X est un DataFrame de vos fonctionnalités et y est un DataFrame à une seule colonne de vos étiquettes.

8
cs95

Solution pure pandas

Pour diviser en train/validation/test dans le rapport 70/20/10%:

train_df = df.sample(frac=0.7, random_state=random_seed)
tmp_df = df.drop(train_df.index)
test_df = tmp_df.sample(frac=0.33333, random_state=random_seed)
valid_df = tmp_df.drop(test_df.index)

assert len(df) == len(train_df) + len(valid_df) + len(test_df), "Dataset sizes don't add up"
del tmp_df
0
Tom Hale