web-dev-qa-db-fra.com

Comment créer et tester des échantillons d'une base de données avec des pandas?

J'ai un ensemble de données assez volumineux sous la forme d'une base de données et je me demandais comment je pourrais la scinder en deux échantillons aléatoires (80% et 20%) pour la formation et les tests.

Merci!

211
tooty44

Je voudrais simplement utiliser randn de numpy:

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
236
Andy Hayden

scikit learn's train_test_split est un bon exemple.

from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)
430
gobrewers14

Un échantillon aléatoire de pandas fonctionnera également 

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

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
Napitupulu Jon

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

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 test et train.

11
user1775015

Il y a beaucoup de réponses valables. Ajouter un de plus au groupe . De sklearn.cross_validation import 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
Abhi

Vous pouvez également envisager une division stratifiée en un ensemble d’entraînement et d’essai. La division Startified génère également des ensembles d’entraînement et de test de manière aléatoire, mais de manière à préserver les proportions de classe originales. Cela permet aux ensembles de formation et de test de mieux refléter les propriétés du jeu 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 fournissent les ensembles de formation et de test de votre fichier DataFrame df d'origine.

5
Apogentus

Si vous devez fractionner vos données en fonction de la colonne lables de votre jeu 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 souhaitez contrôler le caractère aléatoire fractionné ou utiliser une graine aléatoire globale.

2
MikeL

C'est ce que j'ai écrit lorsque j'ai eu besoin de scinder un DataFrame. J’ai envisagé d’utiliser l’approche d’Andy ci-dessus, mais je n’ai pas apprécié le fait que je ne puisse pas contrôler exactement la taille des ensembles de données (c’est-à-dire, 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
Anarcho-Chossid
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)
2
Pardhu Gopalam

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.

1
AHonarmand

Il suffit de sélectionner la rangée 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
Makio

Il existe de nombreuses façons de créer un train/test et même des échantillons de validation.

Cas 1: manière classique train_test_split sans aucune option:

from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size=0.3)

Cas 2: cas d'un très petit jeu de données (<500 lignes): afin d'obtenir des résultats pour toutes vos lignes avec cette validation croisée. À la fin, vous aurez une prédiction pour chaque ligne de votre ensemble d’entraînement disponible.

from sklearn.model_selection import KFold
kf = KFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
    reg = RandomForestRegressor(n_estimators=50, random_state=0)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf = reg.fit(X_train, y_train)
    y_hat = clf.predict(X_test)
    y_hat_all.append(y_hat)

Cas 3a: Jeux de données non équilibrés à des fins de classification. A la suite du cas 1, voici la solution équivalente:

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y, test_size=0.3)

Cas 3b: Jeux de données non équilibrés à des fins de classification. A la suite du cas 2, voici la solution équivalente:

from sklearn.model_selection import StratifiedKFold
kf = StratifiedKFold(n_splits=10, random_state=0)
y_hat_all = []
for train_index, test_index in kf.split(X, y):
    reg = RandomForestRegressor(n_estimators=50, random_state=0)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    clf = reg.fit(X_train, y_train)
    y_hat = clf.predict(X_test)
    y_hat_all.append(y_hat)

Cas 4: vous devez créer un ensemble train/test/validation sur big data pour régler les hyperparamètres (60% train, 20% test et 20% val).

from sklearn.model_selection import train_test_split
X_train, X_test_val, y_train, y_test_val = train_test_split(X, y, test_size=0.6)
X_test, X_val, y_test, y_val = train_test_split(X_test_val, y_test_val, stratify=y, test_size=0.5)
1
yannick_leo

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)
1
kiran6

Je pense que vous devez également obtenir une copie et non une tranche de données si vous souhaitez ajouter des colonnes ultérieurement.

msk = np.random.Rand(len(df)) < 0.8
train, test = df[msk].copy(deep = True), df[~msk].copy(deep = True)
0
Hakim

Qu'en est-il de cela? Df est mon cadre de données

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
Akash Jain

Si vous souhaitez avoir une image donnée et deux images sortantes (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
Johnny V

Un peu plus élégant à mon goût est de créer une colonne aléatoire, puis de la scinder, afin que nous puissions obtenir une scission qui conviendra à nos besoins et sera aléatoire. 

def split_df(df, p=[0.8, 0.2]):
import numpy as np
df["Rand"]=np.random.choice(len(p), len(df), p=p)
r = [df[df["Rand"]==val] for val in df["Rand"].unique()]
return r
0
thebeancounter