팬더가있는 하나의 데이터 프레임에서 테스트 및 훈련 샘플을 어떻게 만듭니 까?


322

나는 데이터 프레임 형태의 상당히 큰 데이터 세트를 가지고 있으며 훈련 및 테스트를 위해 데이터 프레임을 두 개의 임의 샘플 (80 % 및 20 %)로 어떻게 분할 할 수 있는지 궁금합니다.

감사!

답변:


346

나는 단지 numpy를 사용합니다 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

3
미안, 내 실수 긴만큼 mskDTYPE이며 bool, df[msk], df.iloc[msk]그리고 df.loc[msk]항상 같은 결과를 반환합니다.
unutbu 2016 년

2
난 당신이 사용한다고 생각 rand하는 < 0.8균일 0과 1 사이의 임의의 숫자를 분산 반환하기 때문에 이해
R. 최대

4
누군가가 정확하게 라인에서 발생하는 파이썬 측면에서 순수하게 설명 할 수 in[12], in[13], in[14]? 여기에서 파이썬 코드 자체를 이해하고 싶습니다
kuatroka

7
사용 대답 sklearn을 에서 gobrewers14은 더 나은 하나입니다. 덜 복잡하고 쉽게 디버깅 할 수 있습니다. 아래 답변을 사용하는 것이 좋습니다.
그래서 S

2
@kuatroka np.random.rand(len(df))len(df)[0, 1] 범위의 임의적이고 균일하게 분포 된 float 값을 가진 크기의 배열입니다 . 는 < 0.8장소에 비교 결과 소자 와이즈 저장을인가한다. 따라서 값 <0.8이 True되고 값> = 0.8이됩니다False
0:40에 Kentzo

623

scikit learn 'strain_test_split 는 좋은 것입니다.

from sklearn.model_selection import train_test_split

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

22
그러나 Pandas Dataframes가 아닌 numpy 배열을 반환합니다.
Bar

124
BTW, 그것은 지금 팬더 Dataframe을 반환하지 않습니다 (단지 Sklearn 0.16.1 테스트)
줄리앙 Marrec

5
KFold를 찾고 있다면 조금 더 복잡합니다. kf = KFold(n, n_folds=folds) for train_index, test_index in kf: X_train, X_test = X.ix[train_index], X.ix[test_index]여기에 전체 예를 참조하십시오 quantstart.com/articles/...
ihadanny

12
새 버전 (0.18, 이전 버전)에서 from sklearn.model_selection import train_test_split대신 가져옵니다 .
Mark

7
최신 SciKit 버전에서는 다음과 같이 호출해야합니다.from sklearn.cross_validation import train_test_split
horseshoe

289

팬더 랜덤 샘플도 작동합니다

train=df.sample(frac=0.8,random_state=200) #random state is a seed value
test=df.drop(train.index)

.index는 DataFrame에서 .index에 대한 설명서가 어디에 / 무엇을 의미합니까? 찾을 수 없습니다.
dmonopoly

1
random_statearg 는 무엇을 하고 있습니까?
Rishabh Agrahari

1
@RishabhAgrahari는 frac arg에 따라 매번 다른 데이터 분할을 무작위로 섞습니다. 임의성을 제어하려면 예와 같이 자신의 시드를 지정할 수 있습니다.
MikeL

4
이것은 sklearn을 가져 오는 것보다 잘 작동하고 더 우아한 해결책 인 것 같습니다. 이것이 더 나은 대답이 아닌 이유가 있습니까?
RajV 2016 년

1
셔플 경우 @peer이 제한은 쉽게 해결할되고 test여기서 지적 세트가 요구된다 stackoverflow.com/questions/29576430/shuffle-dataframe-rows . test=df.drop(train.index).sample(frac=1.0)
Alok Lal

32

scikit-learn 자신의 training_test_split을 사용하여 색인에서 생성합니다.

from sklearn.model_selection 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

3
cross_validation모듈은 현재 사용되지 않습니다 :DeprecationWarning: This module was deprecated in version 0.18 in favor of the model_selection module into which all the refactored classes and functions are moved. Also note that the interface of the new CV iterators are different from that of this module. This module will be removed in 0.20.
해리

20

학습 / 테스트 및 검증 샘플을 작성하는 방법에는 여러 가지가 있습니다.

사례 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 % 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)

13

아래 코드를 사용하여 테스트 및 교육 샘플을 만들 수 있습니다.

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

시험 크기는 시험 및 훈련 데이터 세트에 넣을 데이터의 백분율에 따라 달라질 수 있습니다.


7

많은 유효한 답변이 있습니다. 무리에 하나 더 추가. sklearn.cross_validation에서 가져 오기 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)]

5

계층화 된 훈련 및 테스트 세트를 고려할 수도 있습니다. 시작 부서는 또한 무작위로 교육 및 테스트 세트를 생성하지만 원래 클래스 비율이 유지됩니다. 이를 통해 훈련 및 테스트 세트가 원래 데이터 세트의 속성을 더 잘 반영합니다.

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]는 원본 DataFrame df의 교육 및 테스트 세트를 제공합니다.


지도 학습 학습 작업에 선호되는 전략입니다.
vincentmajor

이것을 사용하려고 할 때 오류가 발생합니다. ValueError : "np.random.shuffle (value_inds)"줄에서 할당 대상이 읽기 전용입니다.
Markus W

4

데이터 세트의 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)

split randomness를 제어하거나 global random seed를 사용하려는 경우 random_state를 전달할 수도 있습니다.


3
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
당신은 짧은 실수가 있습니다. 대상 열을 삭제하기 전에 train_test_split에 넣습니다. data = data.drop (columns = [ 'column_name'], axis = 1)
Anton Erjomin

3

~ (물결 연산자)를 사용하여 df.sample ()을 사용하여 샘플링 된 행을 제외하고 팬더 만 인덱스의 샘플링 및 필터링을 처리하여 두 세트를 얻을 수 있습니다.

train_df = df.sample(frac=0.8, random_state=100)
test_df = df[~df.index.isin(train_df.index)]

2

이것은 DataFrame을 분할해야 할 때 쓴 것입니다. 위의 Andy의 접근 방식을 사용하는 것을 고려했지만 데이터 세트의 크기를 정확하게 제어 할 수 없다는 점은 마음에 들지 않았습니다 (예 : 때로는 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

다음과 같이 df에서 범위 행을 선택하십시오.

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

3
이것은 데이터 프레임의 데이터가 이미 무작위로 정렬 된 경우에만 작동합니다. 데이터 세트가 여러 소스에서 파생되어 동일한 데이터 프레임에 추가 된 경우 위의 방법을 사용하여 교육 / 테스트를 위해 매우 치우친 데이터 세트를 얻을 수 있습니다.
Emil H

1
분할하기 전에 데이터 프레임을 섞을 수 있습니다. stackoverflow.com/questions/29576430/shuffle-dataframe-rows
Makio

1
절대! df코드 스 니펫에 추가하면 (또는 셔플해야합니다) 대답이 향상됩니다.
Emil H

2

위의 많은 훌륭한 답변이 있으므로 numpy라이브러리 를 사용하여 기차 및 테스트 세트의 정확한 샘플 수를 지정하려는 경우 예제를 하나 더 추가하고 싶습니다 .

# set the random seed for the reproducibility
np.random.seed(17)

# e.g. number of samples for the training set is 1000
n_train = 1000

# shuffle the indexes
shuffled_indexes = np.arange(len(data_df))
np.random.shuffle(shuffled_indexes)

# use 'n_train' samples for training and the rest for testing
train_ids = shuffled_indexes[:n_train]
test_ids = shuffled_indexes[n_train:]

train_data = data_df.iloc[train_ids]
train_labels = labels_df.iloc[train_ids]

test_data = data_df.iloc[test_ids]
test_labels = data_df.iloc[test_ids]

2

학습, 테스트 및 유효성 검사와 같은 둘 이상의 클래스로 분할하기 위해 다음을 수행 할 수 있습니다.

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
"대략"을 추가하기 위해 답변을 편집하고 싶을 수 있습니다. 코드를 실행하면 정확한 비율에서 벗어날 수 있습니다. 예를 들어 1000 가지 항목에서 시도했지만 700, 141, 159-70 %, 14 % 및 16 %입니다.
stason

2

팬더 데이터 프레임을 numpy 배열로 변환 한 다음 numpy 배열을 데이터 프레임으로 다시 변환해야합니다

 import pandas as pd
df=pd.read_csv('/content/drive/My Drive/snippet.csv', sep='\t')
from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.2)
train1=pd.DataFrame(train)
test1=pd.DataFrame(test)
train1.to_csv('/content/drive/My Drive/train.csv',sep="\t",header=None, encoding='utf-8', index = False)
test1.to_csv('/content/drive/My Drive/test.csv',sep="\t",header=None, encoding='utf-8', index = False)

스택 오버플로에서는 코드 전용 답변을 사용할 수 없습니다.
VFDan

1

원하는 경우 하나의 데이터 프레임과 두 개의 데이터 프레임 (numpy 배열이 아닌)을 원한다면 트릭을 수행해야합니다.

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

1

df.as_matrix () 함수를 사용하고 Numpy-array를 만들어 전달할 수 있습니다.

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

내 취향에 조금 더 우아한 것은 임의의 열을 만든 다음 나누는 것입니다.이 방법으로 우리는 필요에 따라 무작위로 나눌 수 있습니다.

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

1

numpy로 변환 할 필요가 없습니다. 팬더 df를 사용하여 분할을 수행하면 팬더 df가 반환됩니다.

from sklearn.model_selection import train_test_split

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

0

나중에 열을 추가하려면 데이터 프레임 조각이 아닌 복사본을 가져와야한다고 생각합니다.

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

0

이건 어때요? 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
shuffle = np.random.permutation(len(df))
test_size = int(len(df) * 0.2)
test_aux = shuffle[:test_size]
train_aux = shuffle[test_size:]
TRAIN_DF =df.iloc[train_aux]
TEST_DF = df.iloc[test_aux]

2
제공 한 코드가 질문에 어떻게 대답하는지 설명하면 더 나은 답변이 될 것입니다.
pppery

이 코드는 질문에 대답 할 수 있지만 문제를 해결하는 방법 및 / 또는 이유에 대한 추가 컨텍스트를 제공하면 답변의 장기적인 가치가 향상됩니다.
shaunakde의

첫 번째 줄은 (데이터 프레임의 크기와 관련하여) 섞인 범위를 반환합니다. 두 번째 줄은 테스트 세트의 원하는 부분을 나타냅니다. .문안 인사.
엘리트 D 장군
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.