diff --git a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h
index 77388ff308006d5157bbd1cbb1c460132c78d674..8393766bcb81489c5e2582e2b1a38bb8912a4251 100644
--- a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h
+++ b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.h
@@ -139,6 +139,9 @@ protected:
    */
   void DispatchInputVectors(void) ITK_OVERRIDE;
 
+  /** Fill the output vectors with a special ordering (class partition) */
+  void FillOneOutput(unsigned int outIdx, ogr::DataSource* outDS, bool update) ITK_OVERRIDE;
+
 private:
   PersistentOGRDataToSamplePositionFilter(const Self &); //purposely not implemented
   void operator =(const Self&); //purposely not implemented
diff --git a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx
index e2d8a40810ea938c874108af958fadd66e9ebb4e..cc70bcbb953570890938f3aa1f72993ac487e19b 100644
--- a/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx
+++ b/Modules/Learning/Sampling/include/otbOGRDataToSamplePositionFilter.txx
@@ -308,6 +308,55 @@ PersistentOGRDataToSamplePositionFilter<TInputImage,TMaskImage,TSampler>
     }
 }
 
+template<class TInputImage, class TMaskImage, class TSampler>
+void
+PersistentOGRDataToSamplePositionFilter<TInputImage,TMaskImage,TSampler>
+::FillOneOutput(unsigned int outIdx, ogr::DataSource* outDS, bool update)
+{
+  ogr::Layer outLayer = outDS->GetLayersCount() == 1
+                        ? outDS->GetLayer(0)
+                        : outDS->GetLayer(this->GetOutLayerName());
+
+  OGRErr err = outLayer.ogr().StartTransaction();
+  if (err != OGRERR_NONE)
+    {
+    itkExceptionMacro(<< "Unable to start transaction for OGR layer " << outLayer.ogr().GetName() << ".");
+    }
+
+  // output vectors sorted by class
+  for (auto& label : m_ClassPartition)
+    {
+    ogr::Layer inLayer = this->GetInMemoryOutput(label.second,outIdx);
+    if (!inLayer)
+      {
+      continue;
+      }
+
+    // This test only uses 1 input, not compatible with multiple OGRData inputs
+    for(auto tmpIt = inLayer.begin(); tmpIt!=inLayer.end(); ++tmpIt)
+      {
+      if( label.first.compare(tmpIt->ogr().GetFieldAsString(this->GetFieldIndex())) != 0 )
+        continue;
+      if(update)
+        {
+        outLayer.SetFeature( *tmpIt );
+        }
+      else
+        {
+        ogr::Feature dstFeature(outLayer.GetLayerDefn());
+        dstFeature.SetFrom( *tmpIt, TRUE );
+        outLayer.CreateFeature( dstFeature );
+        }
+      }
+    }
+
+  err = outLayer.ogr().CommitTransaction();
+  if (err != OGRERR_NONE)
+    {
+    itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << outLayer.ogr().GetName() << ".");
+    }
+}
+
 // -------------- otb::OGRDataToSamplePositionFilter --------------------------
 
 template<class TInputImage, class TMaskImage, class TSampler>
diff --git a/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.h b/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.h
index 8e80fb9e0e77c81e28834d36b1921b09768266a9..bb3b0ac40623ccd7766562f13755ad3e18cae45d 100644
--- a/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.h
+++ b/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.h
@@ -165,6 +165,9 @@ protected:
   /** Gather the content of in-memory output layer into the filter outputs */
   virtual void GatherOutputVectors(void);
 
+  /** Fill output vectors for a particular output */
+  virtual void FillOneOutput(unsigned int outIdx, ogr::DataSource* outDS, bool update);
+
   /** Utility method to add new fields on an output layer */
   virtual void InitializeOutputDataSource(ogr::DataSource* inputDS, ogr::DataSource* outputDS);
 
diff --git a/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.txx b/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.txx
index f10ace96a9ba43e0194a191e2bcd57320fed310a..2973a7a8a3a2e251cdef0ffcf55f034eb6b217aa 100644
--- a/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.txx
+++ b/Modules/Learning/Sampling/include/otbPersistentSamplingFilterBase.txx
@@ -275,8 +275,6 @@ PersistentSamplingFilterBase<TInputImage,TMaskImage>
   // clean temporary inputs
   this->m_InMemoryInputs.clear();
 
-  unsigned int numberOfThreads = this->GetNumberOfThreads();
-
   // gather temporary outputs and write to output
   const otb::ogr::DataSource* vectors = this->GetOGRData();
   otb::Stopwatch chrono = otb::Stopwatch::StartNew();
@@ -287,58 +285,67 @@ PersistentSamplingFilterBase<TInputImage,TMaskImage>
         this->itk::ProcessObject::GetOutput(k));
     if (realOutput)
       {
-      ogr::Layer outLayer = realOutput->GetLayersCount() == 1
-                            ? realOutput->GetLayer(0)
-                            : realOutput->GetLayer(m_OutLayerName);
+      this->FillOneOutput(count, realOutput, bool(vectors == realOutput));
+      count++;
+      }
+    }
 
-      OGRErr err = outLayer.ogr().StartTransaction();
-      if (err != OGRERR_NONE)
-        {
-        itkExceptionMacro(<< "Unable to start transaction for OGR layer " << outLayer.ogr().GetName() << ".");
-        }
+  chrono.Stop();
+  otbMsgDebugMacro(<< "Writing OGR points took " << chrono.GetElapsedMilliseconds() << " ms");
+  this->m_InMemoryOutputs.clear();
+}
 
-      for (unsigned int thread=0 ; thread < numberOfThreads ; thread++)
-        {
-        ogr::Layer inLayer = this->m_InMemoryOutputs[thread][count]->GetLayerChecked(0);
-        if (!inLayer)
-          {
-          continue;
-          }
+template <class TInputImage, class TMaskImage>
+void
+PersistentSamplingFilterBase<TInputImage,TMaskImage>
+::FillOneOutput(unsigned int outIdx, ogr::DataSource* outDS, bool update)
+{
+  ogr::Layer outLayer = outDS->GetLayersCount() == 1
+                        ? outDS->GetLayer(0)
+                        : outDS->GetLayer(m_OutLayerName);
 
-        ogr::Layer::const_iterator tmpIt = inLayer.begin();
-        // This test only uses 1 input, not compatible with multiple OGRData inputs
-        if (vectors == realOutput)
-          {
-          // Update mode
-          for(; tmpIt!=inLayer.end(); ++tmpIt)
-            {
-            outLayer.SetFeature( *tmpIt );
-            }
-          }
-        else
-          {
-          // Copy mode
-          for(; tmpIt!=inLayer.end(); ++tmpIt)
-            {
-            ogr::Feature dstFeature(outLayer.GetLayerDefn());
-            dstFeature.SetFrom( *tmpIt, TRUE );
-            outLayer.CreateFeature( dstFeature );
-            }
-          }
-        }
+  OGRErr err = outLayer.ogr().StartTransaction();
+  if (err != OGRERR_NONE)
+    {
+    itkExceptionMacro(<< "Unable to start transaction for OGR layer " << outLayer.ogr().GetName() << ".");
+    }
 
-      err = outLayer.ogr().CommitTransaction();
-      if (err != OGRERR_NONE)
+  unsigned int numberOfThreads = this->GetNumberOfThreads();
+  for (unsigned int thread=0 ; thread < numberOfThreads ; thread++)
+    {
+    ogr::Layer inLayer = this->m_InMemoryOutputs[thread][outIdx]->GetLayerChecked(0);
+    if (!inLayer)
+      {
+      continue;
+      }
+
+    ogr::Layer::const_iterator tmpIt = inLayer.begin();
+    // This test only uses 1 input, not compatible with multiple OGRData inputs
+    if (update)
+      {
+      // Update mode
+      for(; tmpIt!=inLayer.end(); ++tmpIt)
         {
-        itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << outLayer.ogr().GetName() << ".");
+        outLayer.SetFeature( *tmpIt );
+        }
+      }
+    else
+      {
+      // Copy mode
+      for(; tmpIt!=inLayer.end(); ++tmpIt)
+        {
+        ogr::Feature dstFeature(outLayer.GetLayerDefn());
+        dstFeature.SetFrom( *tmpIt, TRUE );
+        outLayer.CreateFeature( dstFeature );
         }
-      count++;
       }
     }
 
-  chrono.Stop();
-  otbMsgDebugMacro(<< "Writing OGR points took " << chrono.GetElapsedMilliseconds() << " ms");
-  this->m_InMemoryOutputs.clear();
+  err = outLayer.ogr().CommitTransaction();
+  if (err != OGRERR_NONE)
+    {
+    itkExceptionMacro(<< "Unable to commit transaction for OGR layer " << outLayer.ogr().GetName() << ".");
+    }
 }
 
 template <class TInputImage, class TMaskImage>