it-swarm.com.ru

Как создать тестовые и обучающие образцы из одного кадра данных с пандами?

У меня есть довольно большой набор данных в виде фрейма данных, и мне было интересно, как я смогу разделить фрейм данных на две случайные выборки (80% и 20%) для обучения и тестирования.

Спасибо!

232
tooty44

Я бы просто использовал numpy's 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]

И просто чтобы увидеть это сработало:

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

In [16]: len(train)
Out[16]: 79
236
Andy Hayden

scikit learn's train_test_split хороший вариант.

from sklearn.model_selection import train_test_split

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

Панда случайная выборка также будет работать 

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

Я бы использовал собственный обучающий тест scikit-learn и сгенерировал бы его из индекса

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

Вы можете использовать приведенный ниже код для создания тестовых и обучающих примеров:

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

Размер теста может варьироваться в зависимости от процента данных, которые вы хотите поместить в свой набор данных теста и обучения.

11
user1775015

Есть много действительных ответов. Добавление еще одного в кучу . Из 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

Вы также можете рассмотреть разделение на учебно-испытательный комплекс. Подразделение Startered также генерирует наборы для обучения и тестирования случайным образом, но таким образом, что сохраняются исходные пропорции классов. Это позволяет обучающим и тестовым наборам лучше отражать свойства исходного набора данных.

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] и df [test_inds] дают вам наборы для обучения и тестирования вашего оригинального df.

5
Apogentus

Если вам нужно разделить данные по столбцу lables в вашем наборе данных, вы можете использовать это:

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

и использовать это:

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

вы также можете передать random_state, если вы хотите контролировать случайную разбивку или использовать глобальное случайное начальное число.

2
MikeL

Это то, что я написал, когда мне нужно было разделить DataFrame. Я рассмотрел использование подхода Энди выше, но мне не понравилось, что я не мог точно контролировать размер наборов данных (то есть иногда это 79, иногда 81 и т.д.).

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

Чтобы разделить более чем на два класса, таких как обучение, тестирование и проверка, можно сделать:

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]

Это даст 70% данных для обучения, 15% для тестирования и 15% для проверки.

1
AHonarmand

Просто выберите строку диапазона из DF, как это

row_count = df.shape[0]
split_point = int(row_count*1/5)
test_data, train_data = df[:split_point], df[split_point:]
1
Makio

Есть много способов создать поезд/тест и даже проверочные образцы.

Случай 1: классический способ train_test_split без каких-либо опций:

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

Случай 2: случай очень маленьких наборов данных (<500 строк): чтобы получить результаты для всех ваших строк с помощью этой перекрестной проверки. В конце у вас будет один прогноз для каждой строки вашего доступного учебного набора.

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)

Случай 3a: Несбалансированные наборы данных для целей классификации. Следуя случаю 1, вот эквивалентное решение:

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)

Случай 3b: Несбалансированные наборы данных для целей классификации. Следуя случаю 2, вот эквивалентное решение:

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)

Случай 4: вам нужно создать наборы поездов/тестов/проверок больших данных для настройки гиперпараметров (60% поезд, 20% тест и 20% вал).

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

Вы можете использовать функцию df.as_matrix (), создать Numpy-массив и передать его.

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

Я думаю, вам также нужно получить копию, а не фрагмент данных, если вы хотите добавить столбцы позже.

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

Как насчет этого? Df - мой фрейм данных

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

Если вы хотите иметь один и два фрейма данных (а не пустые массивы), это должно сработать:

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

Немного более элегантно на мой вкус - создать случайный столбец, а затем разделить его, таким образом, мы можем получить разделение, которое будет соответствовать нашим потребностям и будет случайным. 

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