# How to split a Dataset into training and testing for machine learning?

Suppose I have iris data In the Dataset Format.

How to split the iris data Into training and testing for Machine learning?

For example,Transform the data for Classify.

-

Let's use the Titanic dataset

tit = ExampleData[{"Dataset", "Titanic"}];


Let's see it's columns

tit[Union, Keys]


Let's choose an objective

obj = "survived";


Let's add an id to each row

tit = tit[AssociationThread[Range@Length@#, #] &];


Let's create a database that splits the features and objective, to make this general.

titSplit =
tit[All, <|"Features" -> Values@*KeyDrop[obj],
"Objective" -> Key[obj]|>];


Let's split the rows arbitrarily to have a test and train set.

numTraining = 200;
ids = Range@tit[Length];
testIds = ids~RandomSample~numTraining;
trainIds = ids~Complement~testIds;

titUnclass = titSplit[<|"Test" -> testIds, "Train" -> trainIds|>];


Let's train the classifier

cfun = titUnclass["Train", Classify@*Values, #Features -> #Objective &];


Let's create a new dataset appending the classifications as a column in the Test dataset.

titClass =
titUnclass[{"Test" ->
Query[All, Append[#, <|"Classified as" -> cfun@#Features|>] &]}];


Or perhaps just have the results in a separate database results = titUnclass["Test", All, cfun@#Features &];

cfm = titUnclass["Test",
ClassifierMeasurements[cfun, #] & @* Values,
#Features -> #Objective &];

cfm["Accuracy"]

(* 0.75 *)


Edit

This is based on the OP @PhilChang nice suggestion in the comments

RandomSample works on Datasets

rtit = RandomSample@ExampleData[{"Dataset", "Titanic"}];


Split

obj = "survived"; numTrain = 200;
ctit = rtit[<|"Train" -> (;; numTrain), "Test" -> (numTrain + 1 ;;)|>];


Train

cfun = ctit["Train", GroupBy[Key[obj] -> KeyDrop[obj]], Values][
Classify];


Measure

cfm = ctit["Test", GroupBy[Key[obj] -> KeyDrop[obj]], Values][
ClassifierMeasurements[cfun, #] &];
cfm["Accuracy"]

-
I get an Accuracy = 0.63. Naive splitting like this is often biased by the dataset layout, eg, look at the distribution of "class": trainTit[Map[First] /* Counts, "Features"] --> "1st" -> 200 versus testTit[Map[First]...] --> "1st" -> 123, "2nd" -> 277, "3rd" -> 709. Typically, bootstrap or other resampling methods are used to minimize the effects of clustering. Certainly you'd want to randomize the partition. – alancalvitti Aug 12 '14 at 19:49
@alancalvitti I struggled with posting it RandomSampled or not, but I'll edit now. I'll also put both trainTit and testTit inside another database. – Rojo Aug 12 '14 at 19:58
We need to make this easier, probably with a new function. Especially making sure you preserve the frequencies of whatever classes when you do the split. – Taliesin Beynon Aug 12 '14 at 20:30
Thank you all,I learned a lot from it. For this moment the best way maybe: 1. Random the dataset, randsample = RandomSample @ titanic; 2. get train and test data. train = RandSample[;;3000];test = randomSample[3001;;]; 3. transform the data set for classify use. train = titanic[GroupBy[Key[obj]], All, Values@*Normal@*KeyDrop[obj]]; – PhilChang Aug 13 '14 at 6:31
If Only Classify accept a Dataset as its argument:Classify[mydataset,y,{x1,x2,...,xp}] – PhilChang Aug 13 '14 at 6:36