Comment créer des échantillons de test et de formation à partir d'un dataframe avec des pandas?

J'ai un ensemble de données assez volumineux sous la forme d'un dataframe et je me demandais comment je serais capable de diviser le dataframe en deux échantillons aléatoires (80% et 20%) pour la formation et les tests.

Merci!

179
demandé sur tooty44 2014-06-10 21:24:57

16 réponses

, je voudrais juste utiliser numpy est randn:

In [11]: df = pd.DataFrame(np.random.randn(100, 2))

In [12]: msk = np.random.rand(len(df)) < 0.8

In [13]: train = df[msk]

In [14]: test = df[~msk]

Et juste pour voir cela a fonctionné:

In [15]: len(test)
Out[15]: 21

In [16]: len(train)
Out[16]: 79
201
répondu Andy Hayden 2014-06-11 00:30:42

Scikit learn train_test_split est un bon.

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)
368
répondu gobrewers14 2017-11-17 20:30:49

Pandas échantillon aléatoire fonctionnera également

train=df.sample(frac=0.8,random_state=200)
test=df.drop(train.index)
166
répondu PagMax 2016-02-21 01:28:55

J'utiliserais le propre training_test_split de scikit-learn, et le générerais à partir de l'index

from sklearn.cross_validation import train_test_split


y = df.pop('output')
X = df

X_train,X_test,y_train,y_test = train_test_split(X.index,y,test_size=0.2)
X.iloc[X_train] # return dataframe train
24
répondu Napitupulu Jon 2015-10-13 11:11:23

Vous pouvez utiliser le code ci-dessous pour créer des échantillons de test et de train:

from sklearn.model_selection import train_test_split
trainingSet, testSet = train_test_split(df, test_size=0.2)

La Taille du Test peut varier en fonction du pourcentage de données que vous souhaitez mettre dans votre jeu de données de test et de formation.

9
répondu user1775015 2018-03-18 14:29:10

Il y a beaucoup de réponses valables. En ajoutant un de plus au groupe. de sklearn.cross_validation importation train_test_split

#gets a random 80% of the entire set
X_train = X.sample(frac=0.8, random_state=1)
#gets the left out portion of the dataset
X_test = X.loc[~df_model.index.isin(X_train.index)]
6
répondu Abhi 2016-12-09 22:18:03

Vous pouvez également envisager une division stratifiée en ensemble de formation et de test. Startified division génère également des ensembles de formation et de tests aléatoires, mais de telle sorte que les proportions de classe d'origine soient préservées. Cela permet aux ensembles de formation et de test de mieux refléter les propriétés de l'ensemble de données d'origine.

import numpy as np  

def get_train_test_inds(y,train_proportion=0.7):
    '''Generates indices, making random stratified split into training set and testing sets
    with proportions train_proportion and (1-train_proportion) of initial sample.
    y is any iterable indicating classes of each observation in the sample.
    Initial proportions of classes inside training and 
    testing sets are preserved (stratified sampling).
    '''

    y=np.array(y)
    train_inds = np.zeros(len(y),dtype=bool)
    test_inds = np.zeros(len(y),dtype=bool)
    values = np.unique(y)
    for value in values:
        value_inds = np.nonzero(y==value)[0]
        np.random.shuffle(value_inds)
        n = int(train_proportion*len(value_inds))

        train_inds[value_inds[:n]]=True
        test_inds[value_inds[n:]]=True

    return train_inds,test_inds

Df [train_inds] et DF [test_inds] vous donnent les ensembles de formation et de test de votre DF DataFrame d'origine.

5
répondu Apogentus 2014-12-10 23:11:12

C'est ce que j'ai écrit quand j'avais besoin de diviser un DataFrame. J'ai envisagé d'utiliser L'approche D'Andy ci-dessus, mais je n'ai pas aimé que je ne puisse pas contrôler exactement la taille des ensembles de données (c'est-à-dire que ce serait parfois 79, parfois 81, etc.).

def make_sets(data_df, test_portion):
    import random as rnd

    tot_ix = range(len(data_df))
    test_ix = sort(rnd.sample(tot_ix, int(test_portion * len(data_df))))
    train_ix = list(set(tot_ix) ^ set(test_ix))

    test_df = data_df.ix[test_ix]
    train_df = data_df.ix[train_ix]

    return train_df, test_df


train_df, test_df = make_sets(data_df, 0.2)
test_df.head()
2
répondu Anarcho-Chossid 2014-12-25 20:59:11

Il suffit de sélectionner la ligne de plage de df comme ceci

row_count = df.shape[0]
split_point = int(row_count*1/5)
test_data, train_data = df[:split_point], df[split_point:]
1
répondu Makio 2017-08-17 08:23:27

Si vous souhaitez avoir un dataframe et deux dataframes (pas des tableaux numpy), cela devrait faire l'affaire:

def split_data(df, train_perc = 0.8):

   df['train'] = np.random.rand(len(df)) < train_perc

   train = df[df.train == 1]

   test = df[df.train == 0]

   split_data ={'train': train, 'test': test}

   return split_data
0
répondu Johnny V 2015-07-19 21:29:26

Je pense que vous devez également obtenir une copie pas une tranche de dataframe si vous voulez ajouter des colonnes plus tard.

msk = np.random.rand(len(df)) < 0.8
train, test = df[msk].copy(deep = True), df[~msk].copy(deep = True)
0
répondu Hakim 2015-08-04 04:16:06

Vous pouvez utiliser la fonction DF.as_matrix() et créer Numpy-array et le transmettre.

Y = df.pop()
X = df.as_matrix()
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size = 0.2)
model.fit(x_train, y_train)
model.test(x_test)
0
répondu kiran6 2015-11-27 08:50:52

Et ça? df est mon dataframe

total_size=len(df)

train_size=math.floor(0.66*total_size) (2/3 part of my dataset)

#training dataset
train=df.head(train_size)
#test dataset
test=df.tail(len(df) -train_size)
0
répondu Akash Jain 2016-10-13 16:34:46

Si vous devez diviser vos données par rapport à la colonne lables dans votre ensemble de données, vous pouvez utiliser ceci:

def split_to_train_test(df, label_column, train_frac=0.8):
    train_df, test_df = pd.DataFrame(), pd.DataFrame()
    labels = df[label_column].unique()
    for lbl in labels:
        lbl_df = df[df[label_column] == lbl]
        lbl_train_df = lbl_df.sample(frac=train_frac)
        lbl_test_df = lbl_df.drop(lbl_train_df.index)
        print '\n%s:\n---------\ntotal:%d\ntrain_df:%d\ntest_df:%d' % (lbl, len(lbl_df), len(lbl_train_df), len(lbl_test_df))
        train_df = train_df.append(lbl_train_df)
        test_df = test_df.append(lbl_test_df)

    return train_df, test_df

Et l'utiliser:

train, test = split_to_train_test(data, 'class', 0.7)

Vous pouvez également passer random_state si vous voulez contrôler le caractère aléatoire fractionné ou utiliser une graine aléatoire globale.

0
répondu MikeL 2017-11-15 09:50:21

Pour diviser en plus de deux classes telles que train, test et validation, on peut faire:

probs = np.random.rand(len(df))
training_mask = probs < 0.7
test_mask = (probs>=0.7) & (probs < 0.85)
validatoin_mask = probs >= 0.85


df_training = df[training_mask]
df_test = df[test_mask]
df_validation = df[validatoin_mask]

Cela mettra 70% des données en formation, 15% en test et 15% en validation.

0
répondu AHonarmand 2018-03-14 17:43:39
import pandas as pd

from sklearn.model_selection import train_test_split

datafile_name = 'path_to_data_file'

data = pd.read_csv(datafile_name)

target_attribute = data['column_name']

X_train, X_test, y_train, y_test = train_test_split(data, target_attribute, test_size=0.8)
0
répondu Pardhu Gopalam 2018-07-10 17:40:45