Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/DatasetExtensions.cs	(revision 15142)
@@ -20,14 +20,91 @@
 #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;
+    }
+
+    /// <summary>
+    /// Prepares a binary data matrix from a number of factors and specified factor values
+    /// </summary>
+    /// <param name="dataset">A dataset that contains the variable values</param>
+    /// <param name="factorVariables">An enumerable of categorical variables (factors). For each variable an enumerable of values must be specified.</param>
+    /// <param name="rows">An enumerable of row indices for the dataset</param>
+    /// <returns></returns>
+    /// <remarks>Factor variables (categorical variables) are split up into multiple binary variables one for each specified value.</remarks>
+    public static double[,] ToArray(
+      this IDataset dataset,
+      IEnumerable<KeyValuePair<string, IEnumerable<string>>> factorVariables,
+      IEnumerable<int> rows) {
+      // check input variables. Only string variables are allowed.
+      var invalidInputs =
+        factorVariables.Select(kvp => kvp.Key).Where(name => !dataset.VariableHasType<string>(name));
+      if (invalidInputs.Any())
+        throw new NotSupportedException("Unsupported inputs: " + string.Join(", ", invalidInputs));
+
+      int numBinaryColumns = factorVariables.Sum(kvp => kvp.Value.Count());
+
+      List<int> rowsList = rows.ToList();
+      double[,] matrix = new double[rowsList.Count, numBinaryColumns];
+
+      int col = 0;
+      foreach (var kvp in factorVariables) {
+        var varName = kvp.Key;
+        var cats = kvp.Value;
+        if (!cats.Any()) continue;
+        foreach (var cat in cats) {
+          var values = dataset.GetStringValues(varName, rows);
+          int row = 0;
+          foreach (var value in values) {
+            matrix[row, col] = value == cat ? 1 : 0;
+            row++;
+          }
+          col++;
+        }
+      }
+      return matrix;
+    }
+
+    public static IEnumerable<KeyValuePair<string, IEnumerable<string>>> GetFactorVariableValues(
+      this IDataset ds, IEnumerable<string> factorVariables, IEnumerable<int> rows) {
+      return from factor in factorVariables
+             let distinctValues = ds.GetStringValues(factor, rows).Distinct().ToArray()
+             // 1 distinct value => skip (constant)
+             // 2 distinct values => only take one of the two values
+             // >=3 distinct values => create a binary value for each value
+             let reducedValues = distinctValues.Length <= 2
+               ? distinctValues.Take(distinctValues.Length - 1)
+               : distinctValues
+             select new KeyValuePair<string, IEnumerable<string>>(factor, reducedValues);
     }
   }
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/DataAnalysisProblemData.cs	(revision 15142)
@@ -94,4 +94,9 @@
     }
 
+    public double[,] AllowedInputsTrainingValues {
+      get { return Dataset.ToArray(AllowedInputVariables, TrainingIndices); }
+    }
+
+    public double[,] AllowedInputsTestValues { get { return Dataset.ToArray(AllowedInputVariables, TestIndices); } }
     public IntRange TrainingPartition {
       get { return TrainingPartitionParameter.Value; }
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/LinearTransformation.cs	(revision 15142)
@@ -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: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftStandardDistributionTransformation.cs	(revision 15142)
@@ -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: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/ShiftToRangeTransformation.cs	(revision 15142)
@@ -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: stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Implementation/Transformations/Transformation.cs	(revision 15142)
@@ -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: stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/IDataAnalysisProblemData.cs	(revision 15142)
@@ -33,4 +33,7 @@
     IEnumerable<string> AllowedInputVariables { get; }
 
+    double[,] AllowedInputsTrainingValues { get; }
+    double[,] AllowedInputsTestValues { get; }
+
     IntRange TrainingPartition { get; }
     IntRange TestPartition { get; }
Index: stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs
===================================================================
--- stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 15140)
+++ stable/HeuristicLab.Problems.DataAnalysis/3.4/Interfaces/ITransformation.cs	(revision 15142)
@@ -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);
   }
