1
$\begingroup$

I get pixel values ​​from it using reference polygons. Extracted pixel values are in data frame, but one row represent extracted values for single pixel. In the classification I need to split the dataset into test (50%) and training (50%) by class (tree, meadow e.t.c)

I know how to split a set according to classes. However, I want values ​​extracted for one polygon to be assigned to one of the sets (training OR test ) and they were not mixed

For this purpose I want to use the polygon ID (Object Identification). I would like to do this using the createDataPartition function. These are just two sample classes (there are many more)

Here is part of table with extracted values:

"band_1"    "band_2"    "band_3"    "CLASS" "Id"
110 134 119 "tree"  1
112 133 118 "tree"  1
105 125 110 "tree"  2
112 132 117 "tree"  2
109 125 115 "meadow"    6
93  110 101 "meadow"    6
86  106 95  "meadow"    7
105 136 116 "meadow"    7
102 128 111 "meadow"    8
108 129 115 "meadow"    8
113 134 119 "meadow"    8

Here is code:

trainIndeks <- caret::createDataPartition(EXTRACTED$CLASS, p = 0.5, list=FALSE, times = 1)

    dataTrain <- EXTRACTED[trainIndeks,]
    dataTest <- EXTRACTED[-trainIndeks,]
$\endgroup$
2
  • $\begingroup$ However, I do not want to split fields with the same ID (I want a class with the same ID to be in training or test set and not not be splited) - that's exactly what train/test splitting does. Could you please be more specific? What does ID mean in your data set? $\endgroup$ Dec 13, 2019 at 14:05
  • $\begingroup$ I corrected the question. $\endgroup$
    – Nicolas
    Dec 13, 2019 at 15:56

1 Answer 1

1
$\begingroup$

Instead of:

dataTrain <- EXTRACTED[trainIndeks,]
dataTest <- EXTRACTED[-trainIndeks,]

try:

dataTrain <- EXTRACTED[ID %% 2 == 1,]
dataTest  <- EXTRACTED[ID %% 2 == 0,]

dataTrain will contain only odd ID, dataTest only even ones.

Using this method you may lose the balance of CLASS distribution between dataTrain and dataTest, but you may improve it by replication or removing of a few records, or by checking the distribution in other splitting, e.g.

dataTrain <- EXTRACTED[ID %% 4 < 2,]
dataTest  <- EXTRACTED[ID %% 4 > 1,]

EDIT:

For random changing the split, you can use:

set.seed(123)
N <- 10
#N <- round(max(EXTRACTED$ID)/10) # for more random grouping
p <- 0.5 # train/(train+test) ratio
idx <- sample(0:(N-1),round(N*p))
dataTrain <- EXTRACTED[ID %% N %in% idx,]
dataTest  <- EXTRACTED[!(ID %% N %in% idx),]
$\endgroup$
11
  • $\begingroup$ That's not exactly what I mean. I corrected the question $\endgroup$
    – Nicolas
    Dec 13, 2019 at 15:58
  • $\begingroup$ Hm, the previous version of the question and the top of train/test datasets needed (and not mentioned aim - to avoid data leakage) were much clear for me. My solution should be good enough if the number of unique ID is over 20 times higher than the number of unique CLASS - I often use it in similar situations. $\endgroup$ Dec 13, 2019 at 18:06
  • $\begingroup$ I checked and your method works, thank you. Will test on a larger collection and let you know. Could you explain why ,, if the number of unique ID is over 20 times higher than the number of unique CLASS ''? $\endgroup$
    – Nicolas
    Dec 13, 2019 at 18:24
  • $\begingroup$ Number 2 is not acceptable in your case because of specific distribution (pure one CLASS in each ID), 200 would be safe in any case, 20 is in between ;) $\endgroup$ Dec 13, 2019 at 19:16
  • $\begingroup$ Thank you, I have one more question: To better assess the accuracy of the classifier, I use it in a loop, but I don't know how to randomly change the data so that it doesn't always get to the same set (test or training) and goes randomly to the test or training. $\endgroup$
    – Nicolas
    Dec 15, 2019 at 9:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.