For a machine learning project, I would like to split my data into train and test sets keeping the fraction of a particular group consistent among the sets. I have created a dummy data.frame of 40 rows to explain myself. Here, for the group "Region", 20% of the data is "North America" , 50% "Europe, 20% Asia and 10% Oceania. I want to end up with a random subset, e.g. 25% of the entire data, in which the percentage composition of the group "Region" remains unchanged.
In other words, I want to start with this:
City County Region
1 Shangai China Asia
2 Tokyo Japan Asia
3 Osaka Japan Asia
4 Hanoi Vietnam Asia
5 Beijing China Asia
6 Sapporo Japan Asia
7 Tottori Japan Asia
8 Saigon Vietnam Asia
9 Rome Italy Europe
10 Paris France Europe
11 Lisbon Portugal Europe
12 Berlin Germany Europe
13 Madrid Spain Europe
14 Vienna Austria Europe
15 Naples Italy Europe
16 Nice France Europe
17 Porto Portugal Europe
18 Frankfurt Germany Europe
19 Sevilla Spain Europe
20 Salzburg Austria Europe
21 Barcelona Spain Europe
22 Amsterdam Netherlands Europe
23 Bern Switzerland Europe
24 Milan Italy Europe
25 San Sebastian Spain Europe
26 Rotterdam Netherlands Europe
27 Zurich Switzerland Europe
28 Turin Italy Europe
29 Ney York City US North America
30 Toronto Canada North America
31 Mexico City Mexico North America
32 Atlanta US North America
33 Chicago US North America
34 Atlanta US North America
35 Vancouver Canada North America
36 Guadalajara Mexico North America
37 Sydney Australia Oceania
38 Wellington New Zealand Oceania
39 Melbourne Australia Oceania
40 Auckland New Zealand Oceania
And end with this (random selection of rows is important to me):
City County Region
1 New York US North America
2 Mexico City Mexico North America
3 Amsterdam Netherlands Europe
4 Madrid Spain Europe
5 Lisbon Portugal Europe
6 Rome Italy Europe
7 Paris France Europe
8 Tokyo Japan Asia
9 Osaka Japan Asia
10 Wellington New Zealand Oceania
The createDataPartition()
function from the caret
package can be used to assign observations to training and test groups while preserving the percentage distribution within each class of a split variable. We'll illustrate its use with the AlzheimerDisease data from Applied Predictive Modeling.
library(caret)
library(AppliedPredictiveModeling)
set.seed(90125)
data(AlzheimerDisease)
adData = data.frame(diagnosis,predictors)
inTrain = createDataPartition(adData$diagnosis, p = .6)[[1]]
training = adData[ inTrain,]
testing = adData[-inTrain,]
We'll now generate tables for the dependent variables in each data frame, and the Impaired
percentage in each is slightly less than 38%.
> table(training$diagnosis)
Impaired Control
55 146
> table(testing$diagnosis)
Impaired Control
36 96
> 55/146
[1] 0.3767123
> 36/96
[1] 0.375
>
If we take a 75% sample from the data provided with the question, we can partition into a training data frame of 30 rows and a testing frame of 10 rows.
# OP data
textFile <- "id|City|County|Region
1|Shangai|China|Asia
2|Tokyo|Japan|Asia
3|Osaka|Japan|Asia
4|Hanoi|Vietnam|Asia
5|Beijing|China|Asia
6|Sapporo|Japan|Asia
7|Tottori|Japan|Asia
8|Saigon|Vietnam|Asia
9|Rome|Italy|Europe
10|Paris|France|Europe
11|Lisbon|Portugal|Europe
12|Berlin|Germany|Europe
13|Madrid|Spain|Europe
14|Vienna|Austria|Europe
15|Naples|Italy|Europe
16|Nice|France|Europe
17|Porto|Portugal|Europe
18|Frankfurt|Germany|Europe
19|Sevilla|Spain|Europe
20|Salzbourg|Austria|Europe
21|Barcelona|Spain|Europe
22|Amsterdam|Netherlands|Europe
23|Bern|Switzerland|Europe
24|Milan|Italy|Europe
25|SanSebastian|Spain|Europe
26|Rotterdam|Netherlands|Europe
27|Zurich|Switzerland|Europe
28|Turin|Italy|Europe
29|New York City|US|North America
30|Toronto|Canada|North America
31|Mexico City|Mexico|North America
32|Atlanta|US|North America
33|Chicago|US|North America
34|Atlanta|US|North America
35|Vancouver|Canada|North America
36|Guadalajara|Mexico|North America
37|Syndey|Australia|Oceania
38|Wellington|New Zealand|Oceania
39|Melbourn|Australia|Oceania
40|Auckland|New Zealand|Oceania"
data <- read.table(text = textFile,header = TRUE,sep = "|",
stringsAsFactors = FALSE)
set.seed(901250)
inTrain = createDataPartition(data$Region, p = .75)[[1]]
training = data[ inTrain,]
testing = data[-inTrain,]
When we print a table of the test data, we see that Region
is distributed as requested in the question: 20% Asia, 50% Europe, 20% North America, and 10% Oceania.
> table(testing$Region)
Asia Europe NorthAmerica Oceania
2 5 2 1
>
Finally, we'll print the testing
data frame.
> testing
id City County Region
2 2 Tokyo Japan Asia
8 8 Saigon Vietnam Asia
9 9 Rome Italy Europe
17 17 Porto Portugal Europe
19 19 Sevilla Spain Europe
21 21 Barcelona Spain Europe
22 22 Amsterdam Netherlands Europe
32 32 Atlanta US North America
36 36 Guadalajara Mexico North America
38 38 Wellington New Zealand Oceania
>