データをランダムにtrainsetとtestsetに分割するには?

大きなデータセットがあり、それをトレーニングセット(50%)とテストセット(50%)に分けたい。

入力ファイルに100個の例が保存されていて、各行に1個の例が含まれているとする。50行をトレーニングセット、50行をテストセットとして選択する必要がある。

私のアイデアは、まず長さ100(値の範囲は1から100まで)のランダムリストを生成し、最初の50個の要素を50個のトレーニング例の行番号として使用します。テストセットも同様です。

これはMatlabで簡単に実現できる

fid=fopen(datafile);
C = textscan(fid, '%s','delimiter', '\n');
plist=randperm(100);
for i=1:50
    trainstring = C{plist(i)};
    fprintf(train_file,trainstring);
end
for i=51:100
    teststring = C{plist(i)};
    fprintf(test_file,teststring);
end

しかし、Pythonでこの機能を実現するにはどうしたらよいでしょうか?Pythonは初めてで、ファイル全体を配列に読み込んで、特定の行を選択できるかどうかわかりません。

ソリューション

これはPythonでもリストを使って同様にできる(リスト全体がその場でシャッフルされることに注意)。

import random

with open("datafile.txt", "rb") as f:
    data = f.read().split('\n')

random.shuffle(data)

train_data = data[:50]
test_data = data[50:]
解説 (3)
from sklearn.model_selection import train_test_split
import numpy

with open("datafile.txt", "rb") as f:
   data = f.read().split('\n')
   data = numpy.array(data)  #convert array to numpy type array

   x_train ,x_test = train_test_split(data,test_size=0.5)       #test_size=0.5(whole_data)
解説 (2)

numpyを使用することもできます。 データがnumpy.ndarrayに保存されている場合:

import numpy as np
from random import sample
l = 100 #length of data 
f = 50  #number of elements you need
indices = sample(range(l),f)

train_data = data[indices]
test_data = np.delete(data,indices)
解説 (0)

sklearn.cross_validationはバージョン0.18以降非推奨です。代わりに、以下の図のように sklearn.model_selectionを使用する必要があります。

from sklearn.model_selection import train_test_split
import numpy

with open("datafile.txt", "rb") as f:
   data = f.read().split('\n')
   data = numpy.array(data)  #convert array to numpy type array

   x_train ,x_test = train_test_split(data,test_size=0.5)       #test_size=0.5(whole_data)
解説 (0)

@ desmond.carrosの質問に答えるために、私は次のように最良の答えを変更しました。

 import random
 file=open("datafile.txt","r")
 data=list()
 for line in file:
    data.append(line.split(#your preferred delimiter))
 file.close()
 random.shuffle(data)
 train_data = data[:int((len(data)+1)*.80)] #Remaining 80% to training set
 test_data = data[int(len(data)*.80+1):] #Splits 20% data to test set

コードは、データセット全体を80%の列車と20%のテストデータに分割します。

解説 (0)

このアプローチを試すことができます。

import pandas
import sklearn
csv = pandas.read_csv('data.csv')
train, test = sklearn.cross_validation.train_test_split(csv, train_size = 0.5)
解説 (0)

以下は、より一般的なk-foldクロスバリデーション分割を生成します。あなたの50対50のパーティショニングは、以下のk=2にすることで達成されるでしょう。注: このコードをテストしたわけではないが、うまくいくはずである。

import random, math

def k_fold(myfile, myseed=11109, k=3):
    # Load data
    data = open(myfile).readlines()

    # Shuffle input
    random.seed=myseed
    random.shuffle(data)

    # Compute partition size given input k
    len_part=int(math.ceil(len(data)/float(k)))

    # Create one partition per fold
    train={}
    test={}
    for ii in range(k):
        test[ii]  = data[ii*len_part:ii*len_part+len_part]
        train[ii] = [jj for jj in data if jj not in test[ii]]

    return train, test      
解説 (0)

@subin sahayamからの回答の簡単なメモ。

 import random
 file=open("datafile.txt","r")
 data=list()
 for line in file:
    data.append(line.split(#your preferred delimiter))
 file.close()
 random.shuffle(data)
 train_data = data[:int((len(data)+1)*.80)] #Remaining 80% to training set
 test_data = data[int(len(data)*.80+1):] #Splits 20% data to test set

リストサイズが偶数の場合は、下のコードに1を追加しないでください。 代わりに、最初にリストのサイズを確認し、次に1を追加する必要があるかどうかを判断する必要があります。

test_data = data [int(len(data)* .80 + 1):]。

解説 (0)

Pythonはリストを使うので、その違いはあります。Pythonのためのかなり良いライブラリであるNumPyを使うことをお勧めします。

解説 (1)