Pandalarla bir veri çerçevesinden test ve eğitim örnekleri nasıl oluştururum?


323

Bir veri çerçevesi şeklinde oldukça büyük bir veri setim var ve veri çerçevesini eğitim ve test için iki rastgele örneğe (% 80 ve% 20) nasıl ayırabileceğimi merak ediyordum.

Teşekkürler!

Yanıtlar:


346

Ben sadece numpy's kullanmak istiyorsunuz 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]

Ve bunun işe yaradığını görmek için:

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

In [16]: len(train)
Out[16]: 79

3
Üzgünüm, benim hatam. Uzun Olarak mskd_type taşımaktadır bool, df[msk], df.iloc[msk]ve df.loc[msk]hep aynı sonucu döndürür.
unutbu

2
Kullanabileceğin gerektiğini düşünüyorum randiçin < 0.8o tekdüze 0 ile 1 arasında rasgele sayılar dağıtılan döndürür çünkü mantıklı
R. Max

4
Birisi tam olarak hatlarında ne piton açısından tamamen açıklayabilir in[12], in[13], in[14]? Burada piton kodunun kendisini anlamak istiyorum
Kuatroka

7
Kullanarak cevap sklearn gelen gobrewers14 iyi biridir. Hata ayıklamak daha az karmaşık ve kolaydır. Aşağıdaki cevabı kullanmanızı tavsiye ederim.
S

2
@kuatroka [0, 1] aralığında rasgele ve düzgün dağılmış kayan noktalı değerlere sahip np.random.rand(len(df))bir boyut dizisidir len(df). < 0.8Yerinde sonucu karşılaştırma öğeye göre ve mağaza uygular. Böylece değerler <0.8 olur Trueve değer> = 0.8 olurFalse
Kentzo

623

scikit öğrenmektrain_test_split iyi bir şeydir .

from sklearn.model_selection import train_test_split

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

22
Ancak bu sayı dizilerini döndürür, ancak Pandalar Dataframes'i döndürmez
Bar

124
Btw, şimdi bir Pandas Veri Çerçevesi döndürüyor (sadece Sklearn 0.16.1'de test edildi)
Julien Marrec

5
KFold arıyorsanız, ne yazık ki biraz daha karmaşık. 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]tam örneği burada görebilirsiniz: quantstart.com/articles/…
ihadanny

12
Yeni sürümlerde (0.18, belki daha önce), from sklearn.model_selection import train_test_splitbunun yerine içe aktarın .
Mark

7
En yeni SciKit sürümünde şimdi şöyle çağırmanız gerekir:from sklearn.cross_validation import train_test_split
at nalı

289

Pandalar rastgele örnek de çalışacak

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

.İndex anlamı ne / DataFrame'de .index belgeleri nerede? Onu bulamıyorum.
dmonopoly

1
random_statearg ne yapıyor?
Rishabh Agrahari

1
@RishabhAgrahari, kırık argümana göre her seferinde farklı verileri rastgele karıştırır. Rasgeleliği kontrol etmek istiyorsanız, örnekte olduğu gibi kendi tohumunuzu belirtebilirsiniz.
MikeL

4
Bu iyi çalışıyor ve sklearn getirmekten daha zarif bir çözüm gibi görünüyor. Bunun daha iyi kabul edilmiş bir cevap olmaması için bir neden var mı?
RajV

1
@ testBurada belirtildiği gibi karıştırılmış bir set isteniyorsa sınırlamanın kolayca giderilebileceğini stackoverflow.com/questions/29576430/shuffle-dataframe-rows . test=df.drop(train.index).sample(frac=1.0)
Alok Lal

32

Scikit-learn'un kendi training_test_split yöntemini kullanır ve dizinden oluştururdum

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_validationModül artık önerilmemektedir: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.
Harry

20

Bir tren / test ve hatta validasyon örnekleri oluşturmanın birçok yolu vardır.

Durum 1: train_test_splitHerhangi bir seçenek olmadan klasik yol :

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

Durum 2: çok küçük veri kümeleri (<500 satır): Bu çapraz doğrulamayla tüm satırlarınız için sonuç almak amacıyla. Sonunda, mevcut egzersiz setinizin her satırı için bir tahmininiz olacaktır.

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)

Durum 3a: Sınıflandırma amaçlı dengesiz veri setleri. Durum 1'i takiben, eşdeğer bir çözüm var:

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)

Durum 3b: Sınıflandırma amaçlı dengesiz veri setleri. Durum 2'yi takiben, eşdeğer bir çözüm var:

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)

Durum 4: Hiperparametreleri ayarlamak için büyük veriler üzerinde bir tren / test / doğrulama seti oluşturmanız gerekir (% 60 tren,% 20 test ve% 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

Test ve tren örnekleri oluşturmak için aşağıdaki kodu kullanabilirsiniz:

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

Test boyutu, test ve tren veri kümenize koymak istediğiniz verilerin yüzdesine bağlı olarak değişebilir.


7

Birçok geçerli cevap var. Demetlere bir tane daha ekliyoruz. sklearn.cross_validation ithalatından 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

Ayrıca eğitim ve test setine tabakalı bölünmeyi de düşünebilirsiniz. Startified bölümü ayrıca eğitim ve test setini rastgele fakat orijinal sınıf oranlarını koruyacak şekilde üretir. Bu, eğitim ve test setlerini orijinal veri kümesinin özelliklerini daha iyi yansıtır hale getirir.

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] ve df [test_inds] size orijinal DataFrame df'nizin eğitim ve test setlerini verir.


Bu denetimli öğrenme görevleri için tercih edilen stratejidir.
vincentmajor

Bunu kullanmaya çalışırken bir hata alıyorum. ValueError: "np.random.shuffle (value_inds)" satırında atama hedefi salt okunur
Markus W

4

Verilerinizi veri kümenizdeki Etiketler sütununa göre ayırmanız gerekirse bunu kullanabilirsiniz:

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

ve kullanın:

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

ayrıca, bölünmüş rasgele kontrol etmek veya bazı global rasgele tohum kullanmak istiyorsanız random_state iletisini geçebilirsiniz.


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
Kısa bir hatanız var. Hedef sütunu daha önce bırakmalısınız, bunu train_test_split içine koymalısınız. data = data.drop (sütunlar = ['sütun_adı'], eksen = 1)
Anton Erjomin

3

Df.sample () kullanılarak örneklenen satırları hariç tutmak için ~ (dalga işareti operatörü) 'ni kullanarak, pandaların yalnızca dizinleri örnekleme ve filtreleme işlemlerini gerçekleştirmesine izin vererek iki set elde edebilirsiniz.

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

2

Bir DataFrame bölmek gerektiğinde yazdım budur. Andy'nin yaklaşımını kullanmayı düşündüm, ancak veri kümelerinin boyutunu tam olarak kontrol edemediğimi sevmedim (yani bazen 79, bazen 81 vb.).

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

Bunun için df'den aralık satırını seçmeniz yeterlidir

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

3
Bu, yalnızca veri çerçevesindeki veriler rastgele sıralanmışsa işe yarar. Veri kümesi birden fazla kaynaktan türetilmişse ve aynı veri çerçevesine eklenmişse, yukarıdakileri kullanarak eğitim / test için çok eğri bir veri kümesi elde etmek oldukça mümkündür.
Emil H

1
Veri çerçevesini bölmeden önce karıştırabilirsiniz stackoverflow.com/questions/29576430/shuffle-dataframe-rows
Makio

1
Absolutelty! dfKod snippet'inize karıştırılırsa (veya karıştırılmalıdır) eklerseniz , yanıtı geliştirirsiniz.
Emil H

2

Yukarıda birçok harika yanıt var, bu yüzden sadece numpykütüphaneyi kullanarak tren ve test setleri için tam örnek sayısını belirtmek istediğinizde bir örnek daha eklemek istiyorum .

# 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

Tren, test ve doğrulama gibi ikiden fazla sınıfa ayrılmak için aşağıdakiler yapılabilir:

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]

Bu, verilerin yaklaşık% 70'ini eğitime,% 15'ini teste ve% 15'ini onaylamaya yerleştirecektir.


1
Cevabınızı "yaklaşık" eklemek için düzenlemek isteyebilirsiniz, kodu çalıştırırsanız, tam yüzde değerinden oldukça uzakta olabileceğini göreceksiniz. Örneğin 1000 ürün üzerinde denedim ve aldım: 700, 141, 159 - yani% 70,% 14 ve% 16.
stason

2

panda veri çerçevesini numpy dizisine dönüştürmeniz ve sonra numpy dizisini tekrar dataframe'e dönüştürmeniz gerekir

 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)

Yığın Taşması'nda yalnızca kod yanıtları kabul edilemez.
VFDan

1

Eğer dilek bir veri çerçevesine ve iki veri çerçevesine sahip olmaksa (numpy dizileri değil), bu hile yapmalıdır:

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 () işlevini kullanabilir ve Numpy dizisi oluşturabilir ve iletebilirsiniz.

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

Benim zevkime göre biraz daha zarif, rastgele bir sütun oluşturmak ve daha sonra onun tarafından bölünmek, bu şekilde ihtiyaçlarımıza uygun ve rastgele olacak bir bölünme elde edebiliriz.

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'ye dönüştürmeye gerek yok. Bölmeyi yapmak için sadece bir panda df kullanın ve bir panda df dönecektir.

from sklearn.model_selection import train_test_split

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

0

Ben de daha sonra sütun eklemek istiyorsanız bir veri çerçevesi değil bir kopyasını almak gerekir düşünüyorum.

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

0

Buna ne dersin? df benim veri çerçevem

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
Verdiğiniz kodun soruyu nasıl yanıtladığını açıklarsanız, bu daha iyi bir yanıt olacaktır.
pppery

Bu kod soruyu cevaplayabilirken, sorunun nasıl ve / veya neden çözüldüğüne dair ek bağlam sağlamak yanıtlayıcının uzun vadeli değerini artıracaktır.
shaunakde

ilk satır karıştırılmış bir aralık döndürür (veri çerçevesinin boyutuna göre). .Saygılarımızla.
Elyte D General
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.