Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/GaussianProcess/GaussianProcessModel.cs	(revision 14393)
@@ -165,6 +165,5 @@
       try {
         CalculateModel(ds, rows, scaleInputs);
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
@@ -260,7 +259,18 @@
     private static double[,] GetData(IDataset ds, IEnumerable<string> allowedInputs, IEnumerable<int> rows, Scaling scaling) {
       if (scaling != null) {
-        return AlglibUtil.PrepareAndScaleInputMatrix(ds, allowedInputs, rows, scaling);
+        // TODO: completely remove Scaling class
+        List<ITransformation<double>> transformations = new List<ITransformation<double>>();
+
+        foreach (var varName in allowedInputs) {
+          double min;
+          double max;
+          scaling.GetScalingParameters(varName, out min, out max);
+          var add = -min / (max - min);
+          var mult = 1.0 / (max - min);
+          transformations.Add(new LinearTransformation(allowedInputs) { Addend = add, Multiplier = mult });
+        }
+        return ds.ToArray(allowedInputs, transformations, rows);
       } else {
-        return AlglibUtil.PrepareInputMatrix(ds, allowedInputs, rows);
+        return ds.ToArray(allowedInputs, rows);
       }
     }
@@ -334,6 +344,5 @@
         return Enumerable.Range(0, newN)
           .Select(i => ms[i] + Util.ScalarProd(Ks[i], alpha));
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
@@ -381,6 +390,5 @@
         }
         return kss;
-      }
-      catch (alglib.alglibexception ae) {
+      } catch (alglib.alglibexception ae) {
         // wrap exception so that calling code doesn't have to know about alglib implementation
         throw new ArgumentException("There was a problem in the calculation of the Gaussian process model", ae);
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/HeuristicLab.Algorithms.DataAnalysis-3.4.csproj	(revision 14393)
@@ -244,6 +244,4 @@
       <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Linear\AlglibUtil.cs" />
-    <Compile Include="Linear\Scaling.cs" />
     <Compile Include="Linear\LinearDiscriminantAnalysis.cs" />
     <Compile Include="Linear\LinearRegression.cs">
@@ -253,4 +251,5 @@
     <Compile Include="Linear\MultinomialLogitClassificationSolution.cs" />
     <Compile Include="Linear\MultinomialLogitModel.cs" />
+    <Compile Include="Linear\Scaling.cs" />
     <Compile Include="MctsSymbolicRegression\Automaton.cs" />
     <Compile Include="MctsSymbolicRegression\CodeGenerator.cs" />
Index: unk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/AlglibUtil.cs	(revision 14392)
+++ 	(revision )
@@ -1,67 +1,0 @@
-﻿#region License Information
-/* HeuristicLab
- * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
- *
- * This file is part of HeuristicLab.
- *
- * HeuristicLab is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * HeuristicLab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
- */
-#endregion
-
-using System.Collections.Generic;
-using System.Linq;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.Algorithms.DataAnalysis {
-  public static class AlglibUtil {
-    public static double[,] PrepareInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
-      List<string> variablesList = variables.ToList();
-      List<int> rowsList = rows.ToList();
-
-      double[,] matrix = new double[rowsList.Count, variablesList.Count];
-
-      int col = 0;
-      foreach (string column in variables) {
-        var values = dataset.GetDoubleValues(column, rows);
-        int row = 0;
-        foreach (var value in values) {
-          matrix[row, col] = value;
-          row++;
-        }
-        col++;
-      }
-
-      return matrix;
-    }
-    public static double[,] PrepareAndScaleInputMatrix(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, Scaling scaling) {
-      List<string> variablesList = variables.ToList();
-      List<int> rowsList = rows.ToList();
-
-      double[,] matrix = new double[rowsList.Count, variablesList.Count];
-
-      int col = 0;
-      foreach (string column in variables) {
-        var values = scaling.GetScaledValues(dataset, column, rows);
-        int row = 0;
-        foreach (var value in values) {
-          matrix[row, col] = value;
-          row++;
-        }
-        col++;
-      }
-
-      return matrix;
-    }
-  }
-}
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearDiscriminantAnalysis.cs	(revision 14393)
@@ -70,5 +70,5 @@
       IEnumerable<int> rows = problemData.TrainingIndices;
       int nClasses = problemData.ClassNames.Count();
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Linear discriminant analysis does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/LinearRegression.cs	(revision 14393)
@@ -73,5 +73,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Linear regression does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitClassification.cs	(revision 14393)
@@ -70,5 +70,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Multinomial logit classification does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/MultinomialLogitModel.cs	(revision 14393)
@@ -83,5 +83,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray( allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Linear/Scaling.cs	(revision 14393)
@@ -29,4 +29,5 @@
 
 namespace HeuristicLab.Algorithms.DataAnalysis {
+  [Obsolete("Use transformation classes in Problems.DataAnalysis instead")]
   [StorableClass]
   [Item(Name = "Scaling", Description = "Contains information about scaling of variables for data-analysis algorithms.")]
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/LdaInitializer.cs	(revision 14393)
@@ -44,7 +44,7 @@
       var attributes = data.AllowedInputVariables.Count();
 
-      var ldaDs = AlglibUtil.PrepareInputMatrix(data.Dataset,
-                                                data.AllowedInputVariables.Concat(data.TargetVariable.ToEnumerable()),
-                                                data.TrainingIndices);
+      var ldaDs = data.Dataset.ToArray(
+                                       data.AllowedInputVariables.Concat(data.TargetVariable.ToEnumerable()),
+                                       data.TrainingIndices);
 
       // map class values to sequential natural numbers (required by alglib)
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/Initialization/PcaInitializer.cs	(revision 14393)
@@ -44,5 +44,5 @@
       var attributes = data.AllowedInputVariables.Count();
 
-      var pcaDs = AlglibUtil.PrepareInputMatrix(data.Dataset, data.AllowedInputVariables, data.TrainingIndices);
+      var pcaDs = data.Dataset.ToArray(data.AllowedInputVariables, data.TrainingIndices);
 
       int info;
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaGradientCalculator.cs	(revision 14393)
@@ -99,6 +99,6 @@
       }
 
-      var data = AlglibUtil.PrepareInputMatrix(problemData.Dataset, problemData.AllowedInputVariables,
-                                               problemData.TrainingIndices);
+      var data = problemData.Dataset.ToArray(problemData.AllowedInputVariables,
+                                             problemData.TrainingIndices);
       var classes = problemData.Dataset.GetDoubleValues(problemData.TargetVariable, problemData.TrainingIndices).ToArray();
 
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/Nca/NcaModel.cs	(revision 14393)
@@ -86,5 +86,5 @@
 
     public double[,] Reduce(IDataset dataset, IEnumerable<int> rows) {
-      var data = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      var data = dataset.ToArray(allowedInputVariables, rows);
 
       var targets = dataset.GetDoubleValues(TargetVariable, rows).ToArray();
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NearestNeighbour/NearestNeighbourModel.cs	(revision 14393)
@@ -119,5 +119,5 @@
       if (IsCompatibilityLoaded) {
         // no scaling
-        inputMatrix = AlglibUtil.PrepareInputMatrix(dataset,
+        inputMatrix = dataset.ToArray(
           this.allowedInputVariables.Concat(new string[] { targetVariable }),
           rows);
@@ -167,15 +167,9 @@
 
     private static double[,] CreateScaledData(IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows, double[] offsets, double[] factors) {
-      var x = new double[rows.Count(), variables.Count()];
-      var colIdx = 0;
-      foreach (var variableName in variables) {
-        var rowIdx = 0;
-        foreach (var val in dataset.GetDoubleValues(variableName, rows)) {
-          x[rowIdx, colIdx] = (val + offsets[colIdx]) * factors[colIdx];
-          rowIdx++;
-        }
-        colIdx++;
-      }
-      return x;
+      var transforms =
+        variables.Select(
+          (_, colIdx) =>
+            new LinearTransformation(variables) { Addend = offsets[colIdx] * factors[colIdx], Multiplier = factors[colIdx] });
+      return dataset.ToArray(variables, transforms, rows);
     }
 
@@ -187,5 +181,5 @@
       double[,] inputData;
       if (IsCompatibilityLoaded) {
-        inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+        inputData = dataset.ToArray(allowedInputVariables, rows);
       } else {
         inputData = CreateScaledData(dataset, allowedInputVariables, rows, offsets, weights);
@@ -223,5 +217,5 @@
       double[,] inputData;
       if (IsCompatibilityLoaded) {
-        inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+        inputData = dataset.ToArray(allowedInputVariables, rows);
       } else {
         inputData = CreateScaledData(dataset, allowedInputVariables, rows, offsets, weights);
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkClassification.cs	(revision 14393)
@@ -183,5 +183,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network classification does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleClassification.cs	(revision 14393)
@@ -124,7 +124,7 @@
     public NeuralNetworkEnsembleClassification()
       : base() {
-      var validHiddenLayerValues = new ItemSet<IntValue>(new IntValue[] { 
-        (IntValue)new IntValue(0).AsReadOnly(), 
-        (IntValue)new IntValue(1).AsReadOnly(), 
+      var validHiddenLayerValues = new ItemSet<IntValue>(new IntValue[] {
+        (IntValue)new IntValue(0).AsReadOnly(),
+        (IntValue)new IntValue(1).AsReadOnly(),
         (IntValue)new IntValue(2).AsReadOnly() });
       var selectedHiddenLayerValue = (from v in validHiddenLayerValues
@@ -169,5 +169,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network ensemble classification does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleModel.cs	(revision 14393)
@@ -91,5 +91,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
@@ -108,5 +108,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkEnsembleRegression.cs	(revision 14393)
@@ -168,5 +168,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network ensemble regression does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkModel.cs	(revision 14393)
@@ -95,5 +95,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
@@ -112,5 +112,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray( allowedInputVariables, rows);
 
       int n = inputData.GetLength(0);
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/NeuralNetwork/NeuralNetworkRegression.cs	(revision 14393)
@@ -184,5 +184,5 @@
       IEnumerable<string> allowedInputVariables = problemData.AllowedInputVariables;
       IEnumerable<int> rows = problemData.TrainingIndices;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables.Concat(new string[] { targetVariable }), rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables.Concat(new string[] { targetVariable }), rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("Neural network regression does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/RandomForest/RandomForestModel.cs	(revision 14393)
@@ -139,5 +139,5 @@
 
     public IEnumerable<double> GetEstimatedValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -157,5 +157,5 @@
 
     public IEnumerable<double> GetEstimatedVariances(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -175,5 +175,5 @@
 
     public override IEnumerable<double> GetEstimatedClassValues(IDataset dataset, IEnumerable<int> rows) {
-      double[,] inputData = AlglibUtil.PrepareInputMatrix(dataset, AllowedInputVariables, rows);
+      double[,] inputData = dataset.ToArray(AllowedInputVariables, rows);
       AssertInputMatrix(inputData);
 
@@ -294,5 +294,5 @@
       out double rmsError, out double outOfBagRmsError, out double avgRelError, out double outOfBagAvgRelError) {
       var variables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(problemData.Dataset, variables, trainingIndices);
+      double[,] inputMatrix = problemData.Dataset.ToArray(variables, trainingIndices);
 
       alglib.dfreport rep;
@@ -316,5 +316,5 @@
 
       var variables = problemData.AllowedInputVariables.Concat(new string[] { problemData.TargetVariable });
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(problemData.Dataset, variables, trainingIndices);
+      double[,] inputMatrix = problemData.Dataset.ToArray(variables, trainingIndices);
 
       var classValues = problemData.ClassValues.ToArray();
Index: /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs
===================================================================
--- /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Algorithms.DataAnalysis/3.4/kMeans/KMeansClustering.cs	(revision 14393)
@@ -89,5 +89,5 @@
       double[,] centers;
       int[] xyc;
-      double[,] inputMatrix = AlglibUtil.PrepareInputMatrix(dataset, allowedInputVariables, rows);
+      double[,] inputMatrix = dataset.ToArray(allowedInputVariables, rows);
       if (inputMatrix.Cast<double>().Any(x => double.IsNaN(x) || double.IsInfinity(x)))
         throw new NotSupportedException("k-Means clustering does not support NaN or infinity values in the input dataset.");
Index: /trunk/sources/HeuristicLab.Common/3.3/EnumerableExtensions.cs
===================================================================
--- /trunk/sources/HeuristicLab.Common/3.3/EnumerableExtensions.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Common/3.3/EnumerableExtensions.cs	(revision 14393)
@@ -133,4 +133,11 @@
       }
     }
+    public static IEnumerable<T> TakeEvery<T>(this IEnumerable<T> xs, int nth) {
+      int i = 0;
+      foreach (var x in xs) {
+        if (i % nth == 0) yield return x;
+        i++;
+      }
+    }
 
     /// <summary>
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 14393)
@@ -113,5 +113,5 @@
       // don't apply when the check fails
       if (success)
-        return transformation.Apply(data);
+        return transformation.ConfigureAndApply(data);
       else
         return data;
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 14393)
@@ -20,14 +20,36 @@
 #endregion
 
+using System;
 using System.Collections.Generic;
+using System.Linq;
 
 namespace HeuristicLab.Problems.DataAnalysis {
   public static class DatasetExtensions {
-    public static IEnumerable<T> TakeEvery<T>(this IEnumerable<T> xs, int nth) {
-      int i = 0;
-      foreach (var x in xs) {
-        if (i % nth == 0) yield return x;
-        i++;
+    public static double[,] ToArray(this IDataset dataset, IEnumerable<string> variables, IEnumerable<int> rows) {
+      return ToArray(dataset,
+        variables,
+        transformations: variables.Select(_ => (ITransformation<double>)null),  // no transform
+        rows: rows);
+    }
+    public static double[,] ToArray(this IDataset dataset, IEnumerable<string> variables, IEnumerable<ITransformation<double>> transformations, IEnumerable<int> rows) {
+      string[] variablesArr = variables.ToArray();
+      int[] rowsArr = rows.ToArray();
+      ITransformation<double>[] transformArr = transformations.ToArray();
+      if (transformArr.Length != variablesArr.Length)
+        throw new ArgumentException("Number of variables and number of transformations must match.");
+
+      double[,] matrix = new double[rowsArr.Length, variablesArr.Length];
+
+      for (int i = 0; i < variablesArr.Length; i++) {
+        var origValues = dataset.GetDoubleValues(variablesArr[i], rowsArr);
+        var values = transformArr[i] != null ? transformArr[i].Apply(origValues) : origValues;
+        int row = 0;
+        foreach (var value in values) {
+          matrix[row, i] = value;
+          row++;
+        }
       }
+
+      return matrix;
     }
   }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 14393)
@@ -52,5 +52,5 @@
     public double Multiplier {
       get { return MultiplierParameter.Value.Value; }
-      protected set {
+      set {
         MultiplierParameter.Value.Value = value;
       }
@@ -59,5 +59,5 @@
     public double Addend {
       get { return AddendParameter.Value.Value; }
-      protected set {
+      set {
         AddendParameter.Value.Value = value;
       }
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 14393)
@@ -71,5 +71,4 @@
 
     public override IEnumerable<double> Apply(IEnumerable<double> data) {
-      ConfigureParameters(data);
       if (OriginalStandardDeviation.IsAlmost(0.0)) {
         return data;
@@ -94,5 +93,5 @@
     }
 
-    protected void ConfigureParameters(IEnumerable<double> data) {
+    public override void ConfigureParameters(IEnumerable<double> data) {
       OriginalStandardDeviation = data.StandardDeviation();
       OriginalMean = data.Average();
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 14393)
@@ -44,9 +44,4 @@
     }
 
-    public override IEnumerable<double> Apply(IEnumerable<double> data) {
-      ConfigureParameters(data);
-      return base.Apply(data);
-    }
-
     public override bool Check(IEnumerable<double> data, out string errorMsg) {
       ConfigureParameters(data);
@@ -54,5 +49,5 @@
     }
 
-    protected void ConfigureParameters(IEnumerable<double> data) {
+    public override void ConfigureParameters(IEnumerable<double> data) {
       double originalRangeStart = data.Min();
       double originalRangeEnd = data.Max();
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 14393)
@@ -66,5 +66,13 @@
     protected Transformation(IEnumerable<string> allowedColumns) : base(allowedColumns) { }
 
+    public virtual void ConfigureParameters(IEnumerable<T> data) {
+      // override in transformations with parameters
+    }
+
     public abstract IEnumerable<T> Apply(IEnumerable<T> data);
+    public IEnumerable<T> ConfigureAndApply(IEnumerable<T> data) {
+      ConfigureParameters(data);
+      return Apply(data);
+    }
 
     public abstract bool Check(IEnumerable<T> data, out string errorMsg);
Index: /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs
===================================================================
--- /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 14392)
+++ /trunk/sources/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 14393)
@@ -30,4 +30,6 @@
 
   public interface ITransformation<T> : ITransformation {
+    void ConfigureParameters(IEnumerable<T> data);
+    IEnumerable<T> ConfigureAndApply(IEnumerable<T> data);
     IEnumerable<T> Apply(IEnumerable<T> data);
   }
