Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/CheckedTransformationListView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/CheckedTransformationListView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/CheckedTransformationListView.cs	(revision 15535)
@@ -51,5 +51,5 @@
           // TODO: Avoid accessing parent view
           var transformationView = (TransformationView)Parent;
-          var columnNames = transformationView.Content.Data.VariableNames;
+          var columnNames = transformationView.Content.PreprocessingData.VariableNames;
 
           return (ITransformation)typeSelectorDialog.TypeSelector.CreateInstanceOfSelectedType(new[] { columnNames });
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataCompletenessView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataCompletenessView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataCompletenessView.cs	(revision 15535)
@@ -52,11 +52,8 @@
 
     private void InitData() {
-      IDictionary<int, IList<int>> missingValueIndices = Content.SearchLogic.GetMissingValueIndices();
-
-      bool[,] valueMissing = new bool[Content.SearchLogic.Rows, Content.SearchLogic.Columns];
-      foreach (var columnMissingValues in missingValueIndices) {
-        var column = columnMissingValues.Key;
-        foreach (var missingValueIndex in columnMissingValues.Value)
-          valueMissing[missingValueIndex, column] = true;
+      bool[,] valueMissing = new bool[Content.PreprocessingData.Rows, Content.PreprocessingData.Columns];
+      for (int row = 0; row < Content.PreprocessingData.Rows; row++) {
+        for (int column = 0; column < Content.PreprocessingData.Columns; column++)
+          valueMissing[row, column] = Content.PreprocessingData.IsCellEmpty(column, row);
       }
 
@@ -78,5 +75,5 @@
       //custom x axis label
       double from = 0.5;
-      foreach (String columnName in Content.SearchLogic.VariableNames) {
+      foreach (String columnName in Content.PreprocessingData.VariableNames) {
         double to = from + 1;
         chart.ChartAreas[0].AxisX.CustomLabels.Add(from, to, columnName);
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.Designer.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.Designer.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.Designer.cs	(revision 15535)
@@ -54,5 +54,4 @@
       this.mostCommonToolStripMenuItem_Column = new System.Windows.Forms.ToolStripMenuItem();
       this.interpolationToolStripMenuItem_Column = new System.Windows.Forms.ToolStripMenuItem();
-      this.smoothingToolStripMenuItem_Column = new System.Windows.Forms.ToolStripMenuItem();
       this.replaceValueOverSelectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
       this.averageToolStripMenuItem_Selection = new System.Windows.Forms.ToolStripMenuItem();
@@ -63,11 +62,13 @@
       this.btnReplace = new System.Windows.Forms.Button();
       this.toolTip = new System.Windows.Forms.ToolTip(this.components);
-      this.checkInputsTargetButton = new System.Windows.Forms.Button();
-      this.uncheckAllButton = new System.Windows.Forms.Button();
-      this.checkAllButton = new System.Windows.Forms.Button();
+      this.shuffleWithinPartitionsCheckBox = new System.Windows.Forms.CheckBox();
       this.addRowButton = new System.Windows.Forms.Button();
       this.addColumnButton = new System.Windows.Forms.Button();
       this.renameColumnsButton = new System.Windows.Forms.Button();
       this.showVariablesGroupBox = new System.Windows.Forms.GroupBox();
+      this.shuffleAllButton = new System.Windows.Forms.Button();
+      this.checkInputsTargetButton = new System.Windows.Forms.Button();
+      this.uncheckAllButton = new System.Windows.Forms.Button();
+      this.checkAllButton = new System.Windows.Forms.Button();
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
       this.contextMenuCell.SuspendLayout();
@@ -127,6 +128,5 @@
             this.randomToolStripMenuItem_Column,
             this.mostCommonToolStripMenuItem_Column,
-            this.interpolationToolStripMenuItem_Column,
-            this.smoothingToolStripMenuItem_Column});
+            this.interpolationToolStripMenuItem_Column});
       this.replaceValueOverColumnToolStripMenuItem.Name = "replaceValueOverColumnToolStripMenuItem";
       this.replaceValueOverColumnToolStripMenuItem.Size = new System.Drawing.Size(223, 22);
@@ -167,11 +167,4 @@
       this.interpolationToolStripMenuItem_Column.Text = "Interpolation";
       this.interpolationToolStripMenuItem_Column.Click += new System.EventHandler(this.ReplaceWithInterpolation_Column_Click);
-      // 
-      // smoothingToolStripMenuItem_Column
-      // 
-      this.smoothingToolStripMenuItem_Column.Name = "smoothingToolStripMenuItem_Column";
-      this.smoothingToolStripMenuItem_Column.Size = new System.Drawing.Size(155, 22);
-      this.smoothingToolStripMenuItem_Column.Text = "Smoothing";
-      this.smoothingToolStripMenuItem_Column.Click += new System.EventHandler(this.ReplaceWithSmoothing_Selection_Click);
       // 
       // replaceValueOverSelectionToolStripMenuItem
@@ -236,4 +229,68 @@
       this.btnReplace.Click += new System.EventHandler(this.btnReplace_Click);
       // 
+      // shuffleWithinPartitionsCheckBox
+      // 
+      this.shuffleWithinPartitionsCheckBox.AutoSize = true;
+      this.shuffleWithinPartitionsCheckBox.Location = new System.Drawing.Point(444, 30);
+      this.shuffleWithinPartitionsCheckBox.Name = "shuffleWithinPartitionsCheckBox";
+      this.shuffleWithinPartitionsCheckBox.Size = new System.Drawing.Size(102, 17);
+      this.shuffleWithinPartitionsCheckBox.TabIndex = 20;
+      this.shuffleWithinPartitionsCheckBox.Text = "Within Partitions";
+      this.toolTip.SetToolTip(this.shuffleWithinPartitionsCheckBox, "If checked, the Training and Test partitions are shuffled separately. Otherwise a" +
+        "ll data is shuffled.");
+      this.shuffleWithinPartitionsCheckBox.UseVisualStyleBackColor = true;
+      // 
+      // addRowButton
+      // 
+      this.addRowButton.Location = new System.Drawing.Point(338, 26);
+      this.addRowButton.Name = "addRowButton";
+      this.addRowButton.Size = new System.Drawing.Size(83, 23);
+      this.addRowButton.TabIndex = 10;
+      this.addRowButton.Text = "Add Datarow";
+      this.addRowButton.UseVisualStyleBackColor = true;
+      this.addRowButton.Click += new System.EventHandler(this.addRowButton_Click);
+      // 
+      // addColumnButton
+      // 
+      this.addColumnButton.Location = new System.Drawing.Point(338, 0);
+      this.addColumnButton.Name = "addColumnButton";
+      this.addColumnButton.Size = new System.Drawing.Size(83, 23);
+      this.addColumnButton.TabIndex = 10;
+      this.addColumnButton.Text = "Add Variable";
+      this.addColumnButton.UseVisualStyleBackColor = true;
+      this.addColumnButton.Click += new System.EventHandler(this.addColumnButton_Click);
+      // 
+      // renameColumnsButton
+      // 
+      this.renameColumnsButton.Location = new System.Drawing.Point(228, 26);
+      this.renameColumnsButton.Name = "renameColumnsButton";
+      this.renameColumnsButton.Size = new System.Drawing.Size(104, 23);
+      this.renameColumnsButton.TabIndex = 11;
+      this.renameColumnsButton.Text = "Rename Variables";
+      this.renameColumnsButton.UseVisualStyleBackColor = true;
+      this.renameColumnsButton.Click += new System.EventHandler(this.renameColumnsButton_Click);
+      // 
+      // showVariablesGroupBox
+      // 
+      this.showVariablesGroupBox.Controls.Add(this.checkInputsTargetButton);
+      this.showVariablesGroupBox.Controls.Add(this.uncheckAllButton);
+      this.showVariablesGroupBox.Controls.Add(this.checkAllButton);
+      this.showVariablesGroupBox.Location = new System.Drawing.Point(564, 0);
+      this.showVariablesGroupBox.Name = "showVariablesGroupBox";
+      this.showVariablesGroupBox.Size = new System.Drawing.Size(97, 49);
+      this.showVariablesGroupBox.TabIndex = 17;
+      this.showVariablesGroupBox.TabStop = false;
+      this.showVariablesGroupBox.Text = "Show Variables";
+      // 
+      // shuffleAllButton
+      // 
+      this.shuffleAllButton.Location = new System.Drawing.Point(444, 0);
+      this.shuffleAllButton.Name = "shuffleAllButton";
+      this.shuffleAllButton.Size = new System.Drawing.Size(102, 23);
+      this.shuffleAllButton.TabIndex = 19;
+      this.shuffleAllButton.Text = "Shuffle";
+      this.shuffleAllButton.UseVisualStyleBackColor = true;
+      this.shuffleAllButton.Click += new System.EventHandler(this.shuffleAllButton_Click);
+      // 
       // checkInputsTargetButton
       // 
@@ -269,50 +326,10 @@
       this.checkAllButton.Click += new System.EventHandler(this.checkAllButton_Click);
       // 
-      // addRowButton
-      // 
-      this.addRowButton.Location = new System.Drawing.Point(338, 26);
-      this.addRowButton.Name = "addRowButton";
-      this.addRowButton.Size = new System.Drawing.Size(83, 23);
-      this.addRowButton.TabIndex = 10;
-      this.addRowButton.Text = "Add Datarow";
-      this.addRowButton.UseVisualStyleBackColor = true;
-      this.addRowButton.Click += new System.EventHandler(this.addRowButton_Click);
-      // 
-      // addColumnButton
-      // 
-      this.addColumnButton.Location = new System.Drawing.Point(338, 0);
-      this.addColumnButton.Name = "addColumnButton";
-      this.addColumnButton.Size = new System.Drawing.Size(83, 23);
-      this.addColumnButton.TabIndex = 10;
-      this.addColumnButton.Text = "Add Variable";
-      this.addColumnButton.UseVisualStyleBackColor = true;
-      this.addColumnButton.Click += new System.EventHandler(this.addColumnButton_Click);
-      // 
-      // renameColumnsButton
-      // 
-      this.renameColumnsButton.Location = new System.Drawing.Point(228, 26);
-      this.renameColumnsButton.Name = "renameColumnsButton";
-      this.renameColumnsButton.Size = new System.Drawing.Size(104, 23);
-      this.renameColumnsButton.TabIndex = 11;
-      this.renameColumnsButton.Text = "Rename Variables";
-      this.renameColumnsButton.UseVisualStyleBackColor = true;
-      this.renameColumnsButton.Click += new System.EventHandler(this.renameColumnsButton_Click);
-      // 
-      // showVariablesGroupBox
-      // 
-      this.showVariablesGroupBox.Controls.Add(this.checkInputsTargetButton);
-      this.showVariablesGroupBox.Controls.Add(this.uncheckAllButton);
-      this.showVariablesGroupBox.Controls.Add(this.checkAllButton);
-      this.showVariablesGroupBox.Location = new System.Drawing.Point(448, 0);
-      this.showVariablesGroupBox.Name = "showVariablesGroupBox";
-      this.showVariablesGroupBox.Size = new System.Drawing.Size(97, 49);
-      this.showVariablesGroupBox.TabIndex = 17;
-      this.showVariablesGroupBox.TabStop = false;
-      this.showVariablesGroupBox.Text = "Show Variables";
-      // 
       // DataGridContentView
       // 
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+      this.Controls.Add(this.shuffleWithinPartitionsCheckBox);
+      this.Controls.Add(this.shuffleAllButton);
       this.Controls.Add(this.showVariablesGroupBox);
       this.Controls.Add(this.renameColumnsButton);
@@ -335,4 +352,6 @@
       this.Controls.SetChildIndex(this.columnsTextBox, 0);
       this.Controls.SetChildIndex(this.showVariablesGroupBox, 0);
+      this.Controls.SetChildIndex(this.shuffleAllButton, 0);
+      this.Controls.SetChildIndex(this.shuffleWithinPartitionsCheckBox, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
       this.contextMenuCell.ResumeLayout(false);
@@ -361,5 +380,4 @@
     private System.Windows.Forms.Button btnReplace;
     private System.Windows.Forms.ToolTip toolTip;
-    private System.Windows.Forms.ToolStripMenuItem smoothingToolStripMenuItem_Column;
     private System.Windows.Forms.Button addRowButton;
     private System.Windows.Forms.Button addColumnButton;
@@ -369,4 +387,6 @@
     private System.Windows.Forms.Button uncheckAllButton;
     private System.Windows.Forms.Button checkAllButton;
+    private System.Windows.Forms.Button shuffleAllButton;
+    private System.Windows.Forms.CheckBox shuffleWithinPartitionsCheckBox;
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataGridContentView.cs	(revision 15535)
@@ -85,5 +85,5 @@
       base.RegisterContentEvents();
       Content.Changed += Content_Changed;
-      Content.FilterLogic.FilterChanged += FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged += FilterLogic_FilterChanged;
     }
 
@@ -91,5 +91,5 @@
       base.DeregisterContentEvents();
       Content.Changed -= Content_Changed;
-      Content.FilterLogic.FilterChanged -= FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged -= FilterLogic_FilterChanged;
     }
 
@@ -98,5 +98,5 @@
       searchIterator = null;
       if (findAndReplaceDialog != null && !findAndReplaceDialog.IsDisposed) {
-        if (Content.FilterLogic.IsFiltered) {
+        if (Content.PreprocessingData.IsFiltered) {
           findAndReplaceDialog.DisableReplace();
         } else {
@@ -104,5 +104,5 @@
         }
       }
-      btnReplace.Enabled = !Content.FilterLogic.IsFiltered;
+      btnReplace.Enabled = !Content.PreprocessingData.IsFiltered;
     }
 
@@ -126,5 +126,5 @@
       string errorMessage;
       if (!String.IsNullOrEmpty(e.FormattedValue.ToString())) {
-        if (dataGridView.IsCurrentCellInEditMode && Content.FilterLogic.IsFiltered) {
+        if (dataGridView.IsCurrentCellInEditMode && Content.PreprocessingData.IsFiltered) {
           errorMessage = "A filter is active, you cannot modify data. Press ESC to exit edit mode.";
         } else {
@@ -167,5 +167,5 @@
 
       ReplaceTransaction(() => {
-        Content.PreProcessingData.InTransaction(() => {
+        Content.PreprocessingData.InTransaction(() => {
           for (int row = containsHeader ? 1 : 0; row < values.GetLength(1); row++) {
             for (int col = 0; col < values.GetLength(0); col++) {
@@ -177,5 +177,5 @@
               if (string.IsNullOrWhiteSpace(firstRow[i]))
                 firstRow[i] = string.Format("<{0}>", i);
-            Content.PreProcessingData.RenameColumns(firstRow);
+            Content.PreprocessingData.RenameColumns(firstRow);
           }
         });
@@ -224,5 +224,5 @@
       if (e.Button == MouseButtons.Middle) {
         int newIndex = e.ColumnIndex >= 0 ? e.ColumnIndex : 0;
-        Content.PreProcessingData.InsertColumn<double>(newIndex.ToString(), newIndex);
+        Content.PreprocessingData.InsertColumn<double>(newIndex.ToString(), newIndex);
       } else if (e.Button == MouseButtons.Right && Content.SortableView) {
         SortColumn(e.ColumnIndex);
@@ -235,5 +235,5 @@
         if (e.Button == MouseButtons.Middle) {
           int newIndex = e.RowIndex >= 0 ? e.RowIndex : 0;
-          Content.PreProcessingData.InsertRow(newIndex);
+          Content.PreprocessingData.InsertRow(newIndex);
         }
       }
@@ -248,6 +248,6 @@
     }
 
-    private void btnApplySort_Click(object sender, System.EventArgs e) {
-      Content.ManipulationLogic.ReOrderToIndices(virtualRowIndices);
+    private void btnApplySort_Click(object sender, EventArgs e) {
+      Content.ReOrderToIndices(virtualRowIndices);
       OnContentChanged();
     }
@@ -271,5 +271,5 @@
         searchIterator = null;
         DataGridView.SelectionChanged += DataGridView_SelectionChanged_FindAndReplace;
-        if (Content.FilterLogic.IsFiltered) {
+        if (Content.PreprocessingData.IsFiltered) {
           findAndReplaceDialog.DisableReplace();
         }
@@ -405,8 +405,8 @@
       ComparisonOperation comparisonOperation = findAndReplaceDialog.GetComparisonOperation();
       var foundCells = new Dictionary<int, IList<int>>();
-      for (int i = 0; i < Content.FilterLogic.PreprocessingData.Columns; i++) {
+      for (int i = 0; i < Content.PreprocessingData.Columns; i++) {
         var filters = CreateFilters(match, comparisonOperation, i);
 
-        bool[] filteredRows = Content.FilterLogic.GetFilterResult(filters, true);
+        bool[] filteredRows = GetFilterResult(filters, true);
         var foundIndices = new List<int>();
         for (int idx = 0; idx < filteredRows.Length; ++idx) {
@@ -427,6 +427,23 @@
     }
 
+    private bool[] GetFilterResult(IList<IFilter> filters, bool isAndCombination) {
+      IList<IFilter> activeFilters = filters.Where(f => f.Active && f.ConstraintData != null).ToList();
+
+      if (activeFilters.Count == 0) {
+        return Enumerable.Repeat(false, Content.PreprocessingData.Rows).ToArray(); ;
+      }
+
+      var result = Enumerable.Repeat(!isAndCombination, Content.PreprocessingData.Rows).ToArray();
+      foreach (IFilter filter in activeFilters) {
+        bool[] filterResult = filter.Check();
+        for (int row = 0; row < result.Length; ++row) {
+          result[row] = isAndCombination ? result[row] || filterResult[row] : result[row] && filterResult[row];
+        }
+      }
+      return result;
+    }
+
     private List<IFilter> CreateFilters(string match, ComparisonOperation comparisonOperation, int columnIndex) {
-      IPreprocessingData preprocessingData = Content.FilterLogic.PreprocessingData;
+      IPreprocessingData preprocessingData = Content.PreprocessingData;
       IStringConvertibleValue value;
       if (preprocessingData.VariableHasType<double>(columnIndex)) {
@@ -473,20 +490,20 @@
           switch (findAndReplaceDialog.GetReplaceAction()) {
             case ReplaceAction.Value:
-              Content.ManipulationLogic.ReplaceIndicesByValue(cells, findAndReplaceDialog.GetReplaceText());
+              Content.ReplaceIndicesByString(cells, findAndReplaceDialog.GetReplaceText());
               break;
             case ReplaceAction.Average:
-              Content.ManipulationLogic.ReplaceIndicesByAverageValue(cells, false);
+              Content.ReplaceIndicesByMean(cells, false);
               break;
             case ReplaceAction.Median:
-              Content.ManipulationLogic.ReplaceIndicesByMedianValue(cells, false);
+              Content.ReplaceIndicesByMedianValue(cells, false);
               break;
             case ReplaceAction.Random:
-              Content.ManipulationLogic.ReplaceIndicesByRandomValue(cells, false);
+              Content.ReplaceIndicesByRandomValue(cells, false);
               break;
             case ReplaceAction.MostCommon:
-              Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(cells, false);
+              Content.ReplaceIndicesByMode(cells, false);
               break;
             case ReplaceAction.Interpolation:
-              Content.ManipulationLogic.ReplaceIndicesByLinearInterpolationOfNeighbours(cells);
+              Content.ReplaceIndicesByLinearInterpolationOfNeighbours(cells);
               break;
           }
@@ -506,5 +523,4 @@
 
     #endregion FindAndReplaceDialog
-
     private void dataGridView_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e) {
       if (Content == null) return;
@@ -531,10 +547,5 @@
             medianToolStripMenuItem_Selection.Enabled =
             randomToolStripMenuItem_Column.Enabled =
-            randomToolStripMenuItem_Selection.Enabled = !Content.PreProcessingData.AreAllStringColumns(columnIndices);
-
-          smoothingToolStripMenuItem_Column.Enabled =
-            interpolationToolStripMenuItem_Column.Enabled = !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, 0])
-            && !dataGridView.SelectedCells.Contains(dataGridView[e.ColumnIndex, Content.Rows - 1])
-            && !Content.PreProcessingData.AreAllStringColumns(columnIndices);
+            randomToolStripMenuItem_Selection.Enabled = !Content.PreprocessingData.AreAllStringColumns(columnIndices);
 
           replaceValueOverColumnToolStripMenuItem.Visible = true;
@@ -547,5 +558,5 @@
       base.dataGridView_KeyDown(sender, e);
       //data is in read only mode....
-      if (Content.FilterLogic.IsFiltered) return;
+      if (Content.PreprocessingData.IsFiltered) return;
 
       if (e.KeyCode == Keys.Delete) {
@@ -581,8 +592,7 @@
       }
 
-      foreach (var selectedCell in dataGridView.SelectedCells) {
-        var cell = (DataGridViewCell)selectedCell;
+      foreach (DataGridViewCell cell in dataGridView.SelectedCells) {
         if (!selectedCells.ContainsKey(cell.ColumnIndex))
-          selectedCells.Add(cell.ColumnIndex, new List<int>(1024));
+          selectedCells.Add(cell.ColumnIndex, new List<int>());
         selectedCells[cell.ColumnIndex].Add(cell.RowIndex);
       }
@@ -591,16 +601,8 @@
     }
 
-    private void StartReplacing() {
+    private void ReplaceTransaction(Action action) {
       SuspendRepaint();
-    }
-
-    private void StopReplacing() {
+      action();
       ResumeRepaint(true);
-    }
-
-    private void ReplaceTransaction(Action action) {
-      StartReplacing();
-      action();
-      StopReplacing();
     }
 
@@ -616,13 +618,12 @@
 
     #region ContextMenu Events
-
     private void ReplaceWithAverage_Column_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByAverageValue(GetSelectedCells(), false);
+        Content.ReplaceIndicesByMean(GetSelectedCells(), false);
       });
     }
     private void ReplaceWithAverage_Selection_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByAverageValue(GetSelectedCells(), true);
+        Content.ReplaceIndicesByMean(GetSelectedCells(), true);
       });
     }
@@ -630,10 +631,10 @@
     private void ReplaceWithMedian_Column_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByMedianValue(GetSelectedCells(), false);
+        Content.ReplaceIndicesByMedianValue(GetSelectedCells(), false);
       });
     }
     private void ReplaceWithMedian_Selection_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByMedianValue(GetSelectedCells(), true);
+        Content.ReplaceIndicesByMedianValue(GetSelectedCells(), true);
       });
     }
@@ -641,10 +642,10 @@
     private void ReplaceWithRandom_Column_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByRandomValue(GetSelectedCells(), false);
+        Content.ReplaceIndicesByRandomValue(GetSelectedCells(), false);
       });
     }
     private void ReplaceWithRandom_Selection_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByRandomValue(GetSelectedCells(), true);
+        Content.ReplaceIndicesByRandomValue(GetSelectedCells(), true);
       });
     }
@@ -652,10 +653,10 @@
     private void ReplaceWithMostCommon_Column_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(GetSelectedCells(), false);
+        Content.ReplaceIndicesByMode(GetSelectedCells(), false);
       });
     }
     private void ReplaceWithMostCommon_Selection_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(GetSelectedCells(), true);
+        Content.ReplaceIndicesByMode(GetSelectedCells(), true);
       });
     }
@@ -663,11 +664,5 @@
     private void ReplaceWithInterpolation_Column_Click(object sender, EventArgs e) {
       ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesByLinearInterpolationOfNeighbours(GetSelectedCells());
-      });
-    }
-
-    private void ReplaceWithSmoothing_Selection_Click(object sender, EventArgs e) {
-      ReplaceTransaction(() => {
-        Content.ManipulationLogic.ReplaceIndicesBySmoothing(GetSelectedCells());
+        Content.ReplaceIndicesByLinearInterpolationOfNeighbours(GetSelectedCells());
       });
     }
@@ -675,9 +670,9 @@
 
     private void addRowButton_Click(object sender, EventArgs e) {
-      Content.PreProcessingData.InsertRow(Content.Rows);
+      Content.PreprocessingData.InsertRow(Content.Rows);
     }
 
     private void addColumnButton_Click(object sender, EventArgs e) {
-      Content.PreProcessingData.InsertColumn<double>(Content.Columns.ToString(), Content.Columns);
+      Content.PreprocessingData.InsertColumn<double>(Content.Columns.ToString(), Content.Columns);
     }
 
@@ -686,5 +681,5 @@
 
       if (renameDialog.ShowDialog(this) == DialogResult.OK) {
-        Content.PreProcessingData.RenameColumns(renameDialog.ColumnNames);
+        Content.PreprocessingData.RenameColumns(renameDialog.ColumnNames);
       }
     }
@@ -693,6 +688,6 @@
       foreach (DataGridViewColumn column in DataGridView.Columns) {
         var variable = column.HeaderText;
-        bool isInputTarget = Content.PreProcessingData.InputVariables.Contains(variable)
-          || Content.PreProcessingData.TargetVariable == variable;
+        bool isInputTarget = Content.PreprocessingData.InputVariables.Contains(variable)
+          || Content.PreprocessingData.TargetVariable == variable;
         column.Visible = isInputTarget;
       }
@@ -710,4 +705,8 @@
       }
     }
+
+    private void shuffleAllButton_Click(object sender, EventArgs e) {
+      Content.Shuffle(shuffleWithinPartitionsCheckBox.Checked);
+    }
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 15535)
@@ -49,12 +49,8 @@
       if (Content != null) {
         var data = Content.Data;
-        var filterLogic = new FilterLogic(data);
-        var searchLogic = new SearchLogic(data, filterLogic);
-        var statisticsLogic = new StatisticsLogic(data, searchLogic);
-        var manipulationLogic = new ManipulationLogic(data, searchLogic, statisticsLogic);
 
         var viewShortcuts = new ItemList<IViewShortcut> {
-          new DataGridContent(data, manipulationLogic, filterLogic),
-          new StatisticsContent(data, statisticsLogic),
+          new DataGridContent(data),
+          new StatisticsContent(data),
 
           new LineChartContent(data),
@@ -63,9 +59,9 @@
           new MultiScatterPlotContent(data),
           new CorrelationMatrixContent(Content),
-          new DataCompletenessChartContent(searchLogic),
-
-          new FilterContent(filterLogic),
-          new ManipulationContent(manipulationLogic, searchLogic, filterLogic),
-          new TransformationContent(data, filterLogic)
+          new DataCompletenessChartContent(data),
+
+          new FilterContent(data),
+          new ManipulationContent(data),
+          new TransformationContent(data)
         };
 
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.Designer.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.Designer.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.Designer.cs	(revision 15535)
@@ -46,5 +46,4 @@
     private void InitializeComponent() {
       this.groupBoxFilter = new System.Windows.Forms.GroupBox();
-      this.checkedFilterView = new HeuristicLab.DataPreprocessing.Views.CheckedFilterCollectionView();
       this.groupBoxFilterInfo = new System.Windows.Forms.GroupBox();
       this.lblPercentage = new System.Windows.Forms.Label();
@@ -63,4 +62,5 @@
       this.label3 = new System.Windows.Forms.Label();
       this.bottomPanel = new System.Windows.Forms.Panel();
+      this.checkedFilterView = new HeuristicLab.DataPreprocessing.Views.CheckedFilterCollectionView();
       this.groupBoxFilter.SuspendLayout();
       this.groupBoxFilterInfo.SuspendLayout();
@@ -80,16 +80,4 @@
       this.groupBoxFilter.TabStop = false;
       this.groupBoxFilter.Text = "Filter";
-      // 
-      // checkedFilterView
-      // 
-      this.checkedFilterView.Caption = "filterView";
-      this.checkedFilterView.Content = null;
-      this.checkedFilterView.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.checkedFilterView.Location = new System.Drawing.Point(3, 16);
-      this.checkedFilterView.Name = "checkedFilterView";
-      this.checkedFilterView.ReadOnly = false;
-      this.checkedFilterView.ShowDetails = true;
-      this.checkedFilterView.Size = new System.Drawing.Size(652, 308);
-      this.checkedFilterView.TabIndex = 0;
       // 
       // groupBoxFilterInfo
@@ -185,5 +173,4 @@
       this.rBtnOr.AutoSize = true;
       this.rBtnOr.Cursor = System.Windows.Forms.Cursors.Default;
-      this.rBtnOr.Enabled = false;
       this.rBtnOr.Location = new System.Drawing.Point(53, 6);
       this.rBtnOr.Name = "rBtnOr";
@@ -199,5 +186,4 @@
       this.rBtnAnd.Checked = true;
       this.rBtnAnd.Cursor = System.Windows.Forms.Cursors.Default;
-      this.rBtnAnd.Enabled = false;
       this.rBtnAnd.Location = new System.Drawing.Point(3, 6);
       this.rBtnAnd.Name = "rBtnAnd";
@@ -273,4 +259,16 @@
       this.bottomPanel.Size = new System.Drawing.Size(670, 30);
       this.bottomPanel.TabIndex = 13;
+      // 
+      // checkedFilterView
+      // 
+      this.checkedFilterView.Caption = "filterView";
+      this.checkedFilterView.Content = null;
+      this.checkedFilterView.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.checkedFilterView.Location = new System.Drawing.Point(3, 16);
+      this.checkedFilterView.Name = "checkedFilterView";
+      this.checkedFilterView.ReadOnly = false;
+      this.checkedFilterView.ShowDetails = true;
+      this.checkedFilterView.Size = new System.Drawing.Size(652, 308);
+      this.checkedFilterView.TabIndex = 0;
       // 
       // FilterView
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/FilterView.cs	(revision 15535)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections.Generic;
 using System.Linq;
 using HeuristicLab.Collections;
@@ -44,19 +43,67 @@
     }
 
-    private void InitData() {
-      checkedFilterView.Content = Content.Filters;
-      checkedFilterView.Content.ItemsAdded += Content_ItemsAdded;
-      checkedFilterView.Content.ItemsRemoved += Content_ItemsRemoved;
-      checkedFilterView.Content.CheckedItemsChanged += Content_CheckedItemsChanged;
-    }
-
     protected override void OnContentChanged() {
       base.OnContentChanged();
       if (Content != null) {
-        InitData();
-        UpdateFilterInfo();
+        checkedFilterView.Content = Content.Filters;
+        rBtnAnd.Checked = Content.IsAndCombination;
+        rBtnOr.Checked = !Content.IsAndCombination;
+        UpdateFilter();
+      } else {
+        checkedFilterView.Content = null;
       }
     }
+    protected override void RegisterContentEvents() {
+      base.RegisterContentEvents();
+      Content.Filters.ItemsAdded += Content_ItemsAdded;
+      Content.Filters.ItemsRemoved += Content_ItemsRemoved;
+      Content.Filters.CheckedItemsChanged += Content_CheckedItemsChanged;
+    }
+    protected override void DeregisterContentEvents() {
+      Content.Filters.ItemsAdded -= Content_ItemsAdded;
+      Content.Filters.ItemsRemoved -= Content_ItemsRemoved;
+      Content.Filters.CheckedItemsChanged -= Content_CheckedItemsChanged;
+      base.DeregisterContentEvents();
+    }
 
+    private void UpdateFilter() {
+      bool activeFilters = Content.ActiveFilters.Any();
+      applyFilterButton.Enabled = activeFilters;
+
+      Content.PreprocessingData.ResetFilter();
+
+      int numTotal = Content.PreprocessingData.Rows;
+      int numRemaining = numTotal;
+
+      if (activeFilters) {
+        var remainingRows = Content.GetRemainingRows();
+        numRemaining = remainingRows.Count(x => x);
+
+        if (numRemaining < numTotal) {
+          Content.PreprocessingData.SetFilter(remainingRows);
+        }
+      }
+
+      tbRemaining.Text = numRemaining.ToString();
+      double ratio = numTotal > 0 ? numRemaining / (double)numTotal : 0.0;
+      tbPercentage.Text = ratio.ToString("P4");
+      tbTotal.Text = numTotal.ToString();
+    }
+
+
+    #region Content Events
+    //whenever a new filter is added the preprocessing data is set to the filter
+    private void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IFilter> e) {
+      if (Content != null) {
+        foreach (IFilter filter in e.Items) {
+          filter.ConstrainedValue = Content.PreprocessingData;
+        }
+      }
+    }
+    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IFilter> e) {
+      if (Content != null) {
+        UpdateFilter();
+      }
+    }
     private void Content_CheckedItemsChanged(object sender, Collections.CollectionItemsChangedEventArgs<IFilter> e) {
       if (Content != null) {
@@ -64,61 +111,30 @@
           filter.Active = checkedFilterView.Content.ItemChecked(filter);
         }
-        UpdateFilterInfo();
+        UpdateFilter();
       }
     }
+    #endregion
 
-    private void UpdateFilterInfo() {
-      List<IFilter> filters = Content.Filters.ToList();
-      int activeFilters = filters.Count(c => c.Active);
-      applyFilterButton.Enabled = (activeFilters > 0);
-      rBtnAnd.Enabled = (activeFilters > 0);
-      rBtnOr.Enabled = (activeFilters > 0);
-      Content.FilterLogic.Reset();
-      bool[] result = Content.FilterLogic.Preview(filters, rBtnAnd.Checked);
-
-      int filteredCnt = result.Count(c => !c);
-
-      tbRemaining.Text = filteredCnt.ToString();
-      double percentage = result.Length == 0 ? 0.0 : filteredCnt * 100 / (double)result.Length;
-      tbPercentage.Text = String.Format("{0:0.0000}%", percentage);
-      tbTotal.Text = result.Length.ToString();
+    #region Controls Events
+    private void rBtnAnd_CheckedChanged(object sender, EventArgs e) {
+      if (Content != null) {
+        Content.IsAndCombination = rBtnAnd.Checked;
+        UpdateFilter();
+      }
     }
-
     private void applyFilterButton_Click(object sender, EventArgs e) {
       if (Content != null) {
-        List<IFilter> filters = Content.Filters.ToList();
         //apply filters
-        Content.FilterLogic.Apply(filters, rBtnAnd.Checked);
+        Content.PreprocessingData.PersistFilter();
+        Content.PreprocessingData.ResetFilter();
         //deactivate checked filters
-        filters = checkedFilterView.Content.CheckedItems.ToList();
-        foreach (IFilter filter in filters) {
+        foreach (var filter in Content.Filters.CheckedItems.ToList()) {
           checkedFilterView.Content.SetItemCheckedState(filter, false);
           filter.Active = false;
         }
-        UpdateFilterInfo();
+        UpdateFilter();
       }
     }
-
-    //whenever a new filter is added the preprocessing data is set to the filter
-    private void Content_ItemsAdded(object sender, Collections.CollectionItemsChangedEventArgs<IFilter> e) {
-      if (Content != null) {
-        foreach (IFilter filter in e.Items) {
-          filter.ConstrainedValue = Content.FilterLogic.PreprocessingData;
-        }
-      }
-    }
-
-    private void Content_ItemsRemoved(object sender, CollectionItemsChangedEventArgs<IFilter> e) {
-      if (Content != null) {
-        UpdateFilterInfo();
-      }
-    }
-
-    private void rBtnAnd_CheckedChanged(object sender, EventArgs e) {
-      if (Content != null) {
-        UpdateFilterInfo();
-        Content.IsAndCombination = rBtnAnd.Checked;
-      }
-    }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.Designer.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.Designer.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.Designer.cs	(revision 15535)
@@ -62,14 +62,4 @@
       this.txtDeleteRowsInfo = new System.Windows.Forms.TextBox();
       this.label5 = new System.Windows.Forms.Label();
-      this.tabReplaceMissingValues = new System.Windows.Forms.TabPage();
-      this.txtReplaceValue = new System.Windows.Forms.TextBox();
-      this.cmbVariableNames = new System.Windows.Forms.ComboBox();
-      this.cmbReplaceWith = new System.Windows.Forms.ComboBox();
-      this.lblValueColon = new System.Windows.Forms.Label();
-      this.label8 = new System.Windows.Forms.Label();
-      this.label10 = new System.Windows.Forms.Label();
-      this.tabDataShuffle = new System.Windows.Forms.TabPage();
-      this.shuffleSeparatelyCheckbox = new System.Windows.Forms.CheckBox();
-      this.lblShuffleProperties = new System.Windows.Forms.Label();
       this.grpBoxPreview = new System.Windows.Forms.GroupBox();
       this.tabsPreview = new System.Windows.Forms.TabControl();
@@ -77,17 +67,13 @@
       this.lblPreviewInActive = new System.Windows.Forms.Label();
       this.tabPreviewDeleteColumnsInfo = new System.Windows.Forms.TabPage();
+      this.panel1 = new System.Windows.Forms.Panel();
       this.lblPreviewColumnsInfo = new System.Windows.Forms.Label();
       this.tabPreviewDeleteColumnsVariance = new System.Windows.Forms.TabPage();
+      this.panel2 = new System.Windows.Forms.Panel();
+      this.lblPreviewColumnsVariance = new System.Windows.Forms.Label();
       this.label12 = new System.Windows.Forms.Label();
-      this.lblPreviewColumnsVariance = new System.Windows.Forms.Label();
       this.tabPreviewDeleteRowsInfo = new System.Windows.Forms.TabPage();
       this.lblPreviewRowsInfo = new System.Windows.Forms.Label();
-      this.tabPreviewReplaceMissingValues = new System.Windows.Forms.TabPage();
-      this.lblPreviewReplaceMissingValues = new System.Windows.Forms.Label();
-      this.tabPreviewShuffle = new System.Windows.Forms.TabPage();
-      this.lblPreviewShuffle = new System.Windows.Forms.Label();
       this.label9 = new System.Windows.Forms.Label();
-      this.panel1 = new System.Windows.Forms.Panel();
-      this.panel2 = new System.Windows.Forms.Panel();
       this.grpBoxData.SuspendLayout();
       this.tabsData.SuspendLayout();
@@ -96,34 +82,26 @@
       this.tabDataDeleteColumnsVariance.SuspendLayout();
       this.tabDataDeleteRowsInfo.SuspendLayout();
-      this.tabReplaceMissingValues.SuspendLayout();
-      this.tabDataShuffle.SuspendLayout();
       this.grpBoxPreview.SuspendLayout();
       this.tabsPreview.SuspendLayout();
       this.tabPreviewInactive.SuspendLayout();
       this.tabPreviewDeleteColumnsInfo.SuspendLayout();
+      this.panel1.SuspendLayout();
       this.tabPreviewDeleteColumnsVariance.SuspendLayout();
+      this.panel2.SuspendLayout();
       this.tabPreviewDeleteRowsInfo.SuspendLayout();
-      this.tabPreviewReplaceMissingValues.SuspendLayout();
-      this.tabPreviewShuffle.SuspendLayout();
-      this.panel1.SuspendLayout();
-      this.panel2.SuspendLayout();
       this.SuspendLayout();
       // 
       // lstMethods
       // 
-      this.lstMethods.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.lstMethods.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.lstMethods.FormattingEnabled = true;
-      this.lstMethods.ItemHeight = 16;
       this.lstMethods.Items.AddRange(new object[] {
             "Delete Columns with insufficient Information",
             "Delete Columns with insufficient Variance",
-            "Delete Rows with insufficient Information",
-            "Replace Missing Values",
-            "Shuffle Data"});
-      this.lstMethods.Location = new System.Drawing.Point(4, 4);
-      this.lstMethods.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+            "Delete Rows with insufficient Information"});
+      this.lstMethods.Location = new System.Drawing.Point(3, 3);
       this.lstMethods.Name = "lstMethods";
-      this.lstMethods.Size = new System.Drawing.Size(976, 116);
+      this.lstMethods.Size = new System.Drawing.Size(733, 95);
       this.lstMethods.Sorted = true;
       this.lstMethods.TabIndex = 0;
@@ -134,8 +112,7 @@
       this.btnApply.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
       this.btnApply.Enabled = false;
-      this.btnApply.Location = new System.Drawing.Point(804, 615);
-      this.btnApply.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.btnApply.Location = new System.Drawing.Point(603, 500);
       this.btnApply.Name = "btnApply";
-      this.btnApply.Size = new System.Drawing.Size(172, 28);
+      this.btnApply.Size = new System.Drawing.Size(129, 23);
       this.btnApply.TabIndex = 2;
       this.btnApply.Text = "Apply Manipulation";
@@ -145,12 +122,10 @@
       // grpBoxData
       // 
-      this.grpBoxData.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.grpBoxData.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.grpBoxData.Controls.Add(this.tabsData);
-      this.grpBoxData.Location = new System.Drawing.Point(5, 129);
-      this.grpBoxData.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.grpBoxData.Location = new System.Drawing.Point(4, 105);
       this.grpBoxData.Name = "grpBoxData";
-      this.grpBoxData.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.grpBoxData.Size = new System.Drawing.Size(976, 233);
+      this.grpBoxData.Size = new System.Drawing.Size(732, 189);
       this.grpBoxData.TabIndex = 3;
       this.grpBoxData.TabStop = false;
@@ -159,5 +134,5 @@
       // tabsData
       // 
-      this.tabsData.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.tabsData.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.tabsData.Controls.Add(this.tabPage1);
@@ -165,12 +140,9 @@
       this.tabsData.Controls.Add(this.tabDataDeleteColumnsVariance);
       this.tabsData.Controls.Add(this.tabDataDeleteRowsInfo);
-      this.tabsData.Controls.Add(this.tabReplaceMissingValues);
-      this.tabsData.Controls.Add(this.tabDataShuffle);
       this.tabsData.ItemSize = new System.Drawing.Size(58, 18);
-      this.tabsData.Location = new System.Drawing.Point(8, 23);
-      this.tabsData.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.tabsData.Location = new System.Drawing.Point(6, 19);
       this.tabsData.Name = "tabsData";
       this.tabsData.SelectedIndex = 0;
-      this.tabsData.Size = new System.Drawing.Size(959, 202);
+      this.tabsData.Size = new System.Drawing.Size(719, 164);
       this.tabsData.TabIndex = 3;
       // 
@@ -179,8 +151,7 @@
       this.tabPage1.Controls.Add(this.label7);
       this.tabPage1.Location = new System.Drawing.Point(4, 22);
-      this.tabPage1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabPage1.Name = "tabPage1";
-      this.tabPage1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPage1.Size = new System.Drawing.Size(951, 176);
+      this.tabPage1.Padding = new System.Windows.Forms.Padding(3);
+      this.tabPage1.Size = new System.Drawing.Size(711, 138);
       this.tabPage1.TabIndex = 5;
       this.tabPage1.Text = "tabDataInactive";
@@ -191,8 +162,7 @@
       this.label7.AutoSize = true;
       this.label7.Enabled = false;
-      this.label7.Location = new System.Drawing.Point(4, 4);
-      this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label7.Location = new System.Drawing.Point(3, 3);
       this.label7.Name = "label7";
-      this.label7.Size = new System.Drawing.Size(345, 17);
+      this.label7.Size = new System.Drawing.Size(259, 13);
       this.label7.TabIndex = 1;
       this.label7.Text = "Please select one of the manipulation methods above";
@@ -204,8 +174,7 @@
       this.tabDataDeleteColumnsInformation.Controls.Add(this.label1);
       this.tabDataDeleteColumnsInformation.Location = new System.Drawing.Point(4, 22);
-      this.tabDataDeleteColumnsInformation.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabDataDeleteColumnsInformation.Name = "tabDataDeleteColumnsInformation";
-      this.tabDataDeleteColumnsInformation.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabDataDeleteColumnsInformation.Size = new System.Drawing.Size(951, 176);
+      this.tabDataDeleteColumnsInformation.Padding = new System.Windows.Forms.Padding(3);
+      this.tabDataDeleteColumnsInformation.Size = new System.Drawing.Size(711, 138);
       this.tabDataDeleteColumnsInformation.TabIndex = 0;
       this.tabDataDeleteColumnsInformation.Text = "del columns info";
@@ -215,8 +184,7 @@
       // 
       this.label2.AutoSize = true;
-      this.label2.Location = new System.Drawing.Point(272, 4);
-      this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label2.Location = new System.Drawing.Point(204, 3);
       this.label2.Name = "label2";
-      this.label2.Size = new System.Drawing.Size(120, 17);
+      this.label2.Size = new System.Drawing.Size(89, 13);
       this.label2.TabIndex = 5;
       this.label2.Text = "% missing values.";
@@ -224,8 +192,7 @@
       // txtDeleteColumnsInfo
       // 
-      this.txtDeleteColumnsInfo.Location = new System.Drawing.Point(219, 0);
-      this.txtDeleteColumnsInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.txtDeleteColumnsInfo.Location = new System.Drawing.Point(164, 0);
       this.txtDeleteColumnsInfo.Name = "txtDeleteColumnsInfo";
-      this.txtDeleteColumnsInfo.Size = new System.Drawing.Size(44, 22);
+      this.txtDeleteColumnsInfo.Size = new System.Drawing.Size(34, 20);
       this.txtDeleteColumnsInfo.TabIndex = 4;
       this.txtDeleteColumnsInfo.TextChanged += new System.EventHandler(this.txtDeleteColumnsInfo_TextChanged);
@@ -234,8 +201,7 @@
       // 
       this.label1.AutoSize = true;
-      this.label1.Location = new System.Drawing.Point(4, 4);
-      this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label1.Location = new System.Drawing.Point(3, 3);
       this.label1.Name = "label1";
-      this.label1.Size = new System.Drawing.Size(205, 17);
+      this.label1.Size = new System.Drawing.Size(155, 13);
       this.label1.TabIndex = 3;
       this.label1.Text = "Delete columns with more than ";
@@ -246,8 +212,7 @@
       this.tabDataDeleteColumnsVariance.Controls.Add(this.label4);
       this.tabDataDeleteColumnsVariance.Location = new System.Drawing.Point(4, 22);
-      this.tabDataDeleteColumnsVariance.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabDataDeleteColumnsVariance.Name = "tabDataDeleteColumnsVariance";
-      this.tabDataDeleteColumnsVariance.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabDataDeleteColumnsVariance.Size = new System.Drawing.Size(951, 176);
+      this.tabDataDeleteColumnsVariance.Padding = new System.Windows.Forms.Padding(3);
+      this.tabDataDeleteColumnsVariance.Size = new System.Drawing.Size(711, 138);
       this.tabDataDeleteColumnsVariance.TabIndex = 1;
       this.tabDataDeleteColumnsVariance.Text = "del columns variance";
@@ -256,8 +221,7 @@
       // txtDeleteColumnsVariance
       // 
-      this.txtDeleteColumnsVariance.Location = new System.Drawing.Point(305, 0);
-      this.txtDeleteColumnsVariance.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.txtDeleteColumnsVariance.Location = new System.Drawing.Point(229, 0);
       this.txtDeleteColumnsVariance.Name = "txtDeleteColumnsVariance";
-      this.txtDeleteColumnsVariance.Size = new System.Drawing.Size(179, 22);
+      this.txtDeleteColumnsVariance.Size = new System.Drawing.Size(135, 20);
       this.txtDeleteColumnsVariance.TabIndex = 4;
       this.txtDeleteColumnsVariance.TextChanged += new System.EventHandler(this.txtDeleteColumnsVariance_TextChanged);
@@ -266,8 +230,7 @@
       // 
       this.label4.AutoSize = true;
-      this.label4.Location = new System.Drawing.Point(4, 4);
-      this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label4.Location = new System.Drawing.Point(3, 3);
       this.label4.Name = "label4";
-      this.label4.Size = new System.Drawing.Size(292, 17);
+      this.label4.Size = new System.Drawing.Size(220, 13);
       this.label4.TabIndex = 3;
       this.label4.Text = "Delete columns with a variance smaller than  ";
@@ -279,8 +242,7 @@
       this.tabDataDeleteRowsInfo.Controls.Add(this.label5);
       this.tabDataDeleteRowsInfo.Location = new System.Drawing.Point(4, 22);
-      this.tabDataDeleteRowsInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabDataDeleteRowsInfo.Name = "tabDataDeleteRowsInfo";
-      this.tabDataDeleteRowsInfo.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabDataDeleteRowsInfo.Size = new System.Drawing.Size(951, 176);
+      this.tabDataDeleteRowsInfo.Padding = new System.Windows.Forms.Padding(3);
+      this.tabDataDeleteRowsInfo.Size = new System.Drawing.Size(711, 138);
       this.tabDataDeleteRowsInfo.TabIndex = 2;
       this.tabDataDeleteRowsInfo.Text = "del rows info";
@@ -290,8 +252,7 @@
       // 
       this.label3.AutoSize = true;
-      this.label3.Location = new System.Drawing.Point(252, 4);
-      this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label3.Location = new System.Drawing.Point(189, 3);
       this.label3.Name = "label3";
-      this.label3.Size = new System.Drawing.Size(120, 17);
+      this.label3.Size = new System.Drawing.Size(89, 13);
       this.label3.TabIndex = 8;
       this.label3.Text = "% missing values.";
@@ -299,8 +260,7 @@
       // txtDeleteRowsInfo
       // 
-      this.txtDeleteRowsInfo.Location = new System.Drawing.Point(196, 0);
-      this.txtDeleteRowsInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.txtDeleteRowsInfo.Location = new System.Drawing.Point(147, 0);
       this.txtDeleteRowsInfo.Name = "txtDeleteRowsInfo";
-      this.txtDeleteRowsInfo.Size = new System.Drawing.Size(44, 22);
+      this.txtDeleteRowsInfo.Size = new System.Drawing.Size(34, 20);
       this.txtDeleteRowsInfo.TabIndex = 7;
       this.txtDeleteRowsInfo.TextChanged += new System.EventHandler(this.txtDeleteRowsInfo_TextChanged);
@@ -309,141 +269,19 @@
       // 
       this.label5.AutoSize = true;
-      this.label5.Location = new System.Drawing.Point(4, 4);
-      this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.label5.Location = new System.Drawing.Point(3, 3);
       this.label5.Name = "label5";
-      this.label5.Size = new System.Drawing.Size(182, 17);
+      this.label5.Size = new System.Drawing.Size(138, 13);
       this.label5.TabIndex = 6;
       this.label5.Text = "Delete rows with more than ";
       // 
-      // tabReplaceMissingValues
-      // 
-      this.tabReplaceMissingValues.Controls.Add(this.txtReplaceValue);
-      this.tabReplaceMissingValues.Controls.Add(this.cmbVariableNames);
-      this.tabReplaceMissingValues.Controls.Add(this.cmbReplaceWith);
-      this.tabReplaceMissingValues.Controls.Add(this.lblValueColon);
-      this.tabReplaceMissingValues.Controls.Add(this.label8);
-      this.tabReplaceMissingValues.Controls.Add(this.label10);
-      this.tabReplaceMissingValues.Location = new System.Drawing.Point(4, 22);
-      this.tabReplaceMissingValues.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabReplaceMissingValues.Name = "tabReplaceMissingValues";
-      this.tabReplaceMissingValues.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabReplaceMissingValues.Size = new System.Drawing.Size(951, 176);
-      this.tabReplaceMissingValues.TabIndex = 6;
-      this.tabReplaceMissingValues.Text = "repl missing vals";
-      this.tabReplaceMissingValues.UseVisualStyleBackColor = true;
-      // 
-      // txtReplaceValue
-      // 
-      this.txtReplaceValue.Location = new System.Drawing.Point(231, 33);
-      this.txtReplaceValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.txtReplaceValue.Name = "txtReplaceValue";
-      this.txtReplaceValue.Size = new System.Drawing.Size(132, 22);
-      this.txtReplaceValue.TabIndex = 2;
-      this.txtReplaceValue.TextChanged += new System.EventHandler(this.txtReplaceValue_TextChanged);
-      // 
-      // cmbVariableNames
-      // 
-      this.cmbVariableNames.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.cmbVariableNames.FormattingEnabled = true;
-      this.cmbVariableNames.Location = new System.Drawing.Point(189, 0);
-      this.cmbVariableNames.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.cmbVariableNames.Name = "cmbVariableNames";
-      this.cmbVariableNames.Size = new System.Drawing.Size(160, 24);
-      this.cmbVariableNames.TabIndex = 1;
-      this.cmbVariableNames.SelectedIndexChanged += new System.EventHandler(this.cmbReplaceWith_SelectedIndexChanged);
-      // 
-      // cmbReplaceWith
-      // 
-      this.cmbReplaceWith.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.cmbReplaceWith.FormattingEnabled = true;
-      this.cmbReplaceWith.Items.AddRange(new object[] {
-            "Value",
-            "Average",
-            "Median",
-            "Most Common",
-            "Random"});
-      this.cmbReplaceWith.Location = new System.Drawing.Point(47, 33);
-      this.cmbReplaceWith.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.cmbReplaceWith.Name = "cmbReplaceWith";
-      this.cmbReplaceWith.Size = new System.Drawing.Size(160, 24);
-      this.cmbReplaceWith.TabIndex = 1;
-      this.cmbReplaceWith.SelectedIndexChanged += new System.EventHandler(this.cmbReplaceWith_SelectedIndexChanged);
-      // 
-      // lblValueColon
-      // 
-      this.lblValueColon.AutoSize = true;
-      this.lblValueColon.Location = new System.Drawing.Point(209, 37);
-      this.lblValueColon.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.lblValueColon.Name = "lblValueColon";
-      this.lblValueColon.Size = new System.Drawing.Size(12, 17);
-      this.lblValueColon.TabIndex = 0;
-      this.lblValueColon.Text = ":";
-      // 
-      // label8
-      // 
-      this.label8.AutoSize = true;
-      this.label8.Location = new System.Drawing.Point(4, 37);
-      this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.label8.Name = "label8";
-      this.label8.Size = new System.Drawing.Size(32, 17);
-      this.label8.TabIndex = 0;
-      this.label8.Text = "with";
-      // 
-      // label10
-      // 
-      this.label10.AutoSize = true;
-      this.label10.Location = new System.Drawing.Point(4, 4);
-      this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.label10.Name = "label10";
-      this.label10.Size = new System.Drawing.Size(177, 17);
-      this.label10.TabIndex = 0;
-      this.label10.Text = "Replace missing values for";
-      // 
-      // tabDataShuffle
-      // 
-      this.tabDataShuffle.Controls.Add(this.shuffleSeparatelyCheckbox);
-      this.tabDataShuffle.Controls.Add(this.lblShuffleProperties);
-      this.tabDataShuffle.Location = new System.Drawing.Point(4, 22);
-      this.tabDataShuffle.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabDataShuffle.Name = "tabDataShuffle";
-      this.tabDataShuffle.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabDataShuffle.Size = new System.Drawing.Size(951, 176);
-      this.tabDataShuffle.TabIndex = 4;
-      this.tabDataShuffle.Text = "shuffle";
-      this.tabDataShuffle.UseVisualStyleBackColor = true;
-      // 
-      // shuffleSeparatelyCheckbox
-      // 
-      this.shuffleSeparatelyCheckbox.AutoSize = true;
-      this.shuffleSeparatelyCheckbox.Location = new System.Drawing.Point(8, 2);
-      this.shuffleSeparatelyCheckbox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.shuffleSeparatelyCheckbox.Name = "shuffleSeparatelyCheckbox";
-      this.shuffleSeparatelyCheckbox.Size = new System.Drawing.Size(312, 21);
-      this.shuffleSeparatelyCheckbox.TabIndex = 1;
-      this.shuffleSeparatelyCheckbox.Text = "Shuffle training and test partitions separately";
-      this.shuffleSeparatelyCheckbox.UseVisualStyleBackColor = true;
-      // 
-      // lblShuffleProperties
-      // 
-      this.lblShuffleProperties.AutoSize = true;
-      this.lblShuffleProperties.Enabled = false;
-      this.lblShuffleProperties.Location = new System.Drawing.Point(4, 4);
-      this.lblShuffleProperties.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.lblShuffleProperties.Name = "lblShuffleProperties";
-      this.lblShuffleProperties.Size = new System.Drawing.Size(154, 17);
-      this.lblShuffleProperties.TabIndex = 0;
-      this.lblShuffleProperties.Text = "No properties available";
-      // 
       // grpBoxPreview
       // 
-      this.grpBoxPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
-            | System.Windows.Forms.AnchorStyles.Left)
+      this.grpBoxPreview.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
+            | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.grpBoxPreview.Controls.Add(this.tabsPreview);
-      this.grpBoxPreview.Location = new System.Drawing.Point(5, 370);
-      this.grpBoxPreview.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.grpBoxPreview.Location = new System.Drawing.Point(4, 301);
       this.grpBoxPreview.Name = "grpBoxPreview";
-      this.grpBoxPreview.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.grpBoxPreview.Size = new System.Drawing.Size(976, 238);
+      this.grpBoxPreview.Size = new System.Drawing.Size(732, 193);
       this.grpBoxPreview.TabIndex = 4;
       this.grpBoxPreview.TabStop = false;
@@ -452,5 +290,5 @@
       // tabsPreview
       // 
-      this.tabsPreview.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+      this.tabsPreview.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
             | System.Windows.Forms.AnchorStyles.Right)));
       this.tabsPreview.Controls.Add(this.tabPreviewInactive);
@@ -458,12 +296,9 @@
       this.tabsPreview.Controls.Add(this.tabPreviewDeleteColumnsVariance);
       this.tabsPreview.Controls.Add(this.tabPreviewDeleteRowsInfo);
-      this.tabsPreview.Controls.Add(this.tabPreviewReplaceMissingValues);
-      this.tabsPreview.Controls.Add(this.tabPreviewShuffle);
       this.tabsPreview.ItemSize = new System.Drawing.Size(58, 18);
-      this.tabsPreview.Location = new System.Drawing.Point(8, 23);
-      this.tabsPreview.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+      this.tabsPreview.Location = new System.Drawing.Point(6, 19);
       this.tabsPreview.Name = "tabsPreview";
       this.tabsPreview.SelectedIndex = 0;
-      this.tabsPreview.Size = new System.Drawing.Size(959, 207);
+      this.tabsPreview.Size = new System.Drawing.Size(719, 168);
       this.tabsPreview.TabIndex = 3;
       // 
@@ -472,8 +307,7 @@
       this.tabPreviewInactive.Controls.Add(this.lblPreviewInActive);
       this.tabPreviewInactive.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewInactive.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabPreviewInactive.Name = "tabPreviewInactive";
-      this.tabPreviewInactive.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewInactive.Size = new System.Drawing.Size(951, 181);
+      this.tabPreviewInactive.Padding = new System.Windows.Forms.Padding(3);
+      this.tabPreviewInactive.Size = new System.Drawing.Size(711, 142);
       this.tabPreviewInactive.TabIndex = 5;
       this.tabPreviewInactive.Text = "inactive";
@@ -483,8 +317,7 @@
       // 
       this.lblPreviewInActive.AutoSize = true;
-      this.lblPreviewInActive.Location = new System.Drawing.Point(4, 4);
-      this.lblPreviewInActive.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.lblPreviewInActive.Location = new System.Drawing.Point(3, 3);
       this.lblPreviewInActive.Name = "lblPreviewInActive";
-      this.lblPreviewInActive.Size = new System.Drawing.Size(491, 51);
+      this.lblPreviewInActive.Size = new System.Drawing.Size(361, 39);
       this.lblPreviewInActive.TabIndex = 2;
       this.lblPreviewInActive.Text = "Filters are active and thus manipulations cannot be applied!\r\n\r\nPlease deactive t" +
@@ -496,12 +329,22 @@
       this.tabPreviewDeleteColumnsInfo.Controls.Add(this.panel1);
       this.tabPreviewDeleteColumnsInfo.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewDeleteColumnsInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabPreviewDeleteColumnsInfo.Name = "tabPreviewDeleteColumnsInfo";
-      this.tabPreviewDeleteColumnsInfo.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewDeleteColumnsInfo.Size = new System.Drawing.Size(951, 181);
+      this.tabPreviewDeleteColumnsInfo.Padding = new System.Windows.Forms.Padding(3);
+      this.tabPreviewDeleteColumnsInfo.Size = new System.Drawing.Size(711, 142);
       this.tabPreviewDeleteColumnsInfo.TabIndex = 0;
       this.tabPreviewDeleteColumnsInfo.Text = "del columns info";
       this.tabPreviewDeleteColumnsInfo.UseVisualStyleBackColor = true;
       // 
+      // panel1
+      // 
+      this.panel1.AutoScroll = true;
+      this.panel1.Controls.Add(this.lblPreviewColumnsInfo);
+      this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.panel1.Location = new System.Drawing.Point(3, 3);
+      this.panel1.Margin = new System.Windows.Forms.Padding(2);
+      this.panel1.Name = "panel1";
+      this.panel1.Size = new System.Drawing.Size(705, 136);
+      this.panel1.TabIndex = 2;
+      // 
       // lblPreviewColumnsInfo
       // 
@@ -509,7 +352,6 @@
       this.lblPreviewColumnsInfo.Dock = System.Windows.Forms.DockStyle.Left;
       this.lblPreviewColumnsInfo.Location = new System.Drawing.Point(0, 0);
-      this.lblPreviewColumnsInfo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
       this.lblPreviewColumnsInfo.Name = "lblPreviewColumnsInfo";
-      this.lblPreviewColumnsInfo.Size = new System.Drawing.Size(423, 17);
+      this.lblPreviewColumnsInfo.Size = new System.Drawing.Size(318, 13);
       this.lblPreviewColumnsInfo.TabIndex = 1;
       this.lblPreviewColumnsInfo.Text = "{0} columns with more than {1} % missing values would be deleted";
@@ -520,20 +362,21 @@
       this.tabPreviewDeleteColumnsVariance.Controls.Add(this.label12);
       this.tabPreviewDeleteColumnsVariance.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewDeleteColumnsVariance.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabPreviewDeleteColumnsVariance.Name = "tabPreviewDeleteColumnsVariance";
-      this.tabPreviewDeleteColumnsVariance.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewDeleteColumnsVariance.Size = new System.Drawing.Size(951, 181);
+      this.tabPreviewDeleteColumnsVariance.Padding = new System.Windows.Forms.Padding(3);
+      this.tabPreviewDeleteColumnsVariance.Size = new System.Drawing.Size(711, 142);
       this.tabPreviewDeleteColumnsVariance.TabIndex = 1;
       this.tabPreviewDeleteColumnsVariance.Text = "del columns variance";
       this.tabPreviewDeleteColumnsVariance.UseVisualStyleBackColor = true;
       // 
-      // label12
-      // 
-      this.label12.AutoSize = true;
-      this.label12.Location = new System.Drawing.Point(8, 27);
-      this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.label12.Name = "label12";
-      this.label12.Size = new System.Drawing.Size(0, 17);
-      this.label12.TabIndex = 2;
+      // panel2
+      // 
+      this.panel2.AutoScroll = true;
+      this.panel2.Controls.Add(this.lblPreviewColumnsVariance);
+      this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
+      this.panel2.Location = new System.Drawing.Point(3, 3);
+      this.panel2.Margin = new System.Windows.Forms.Padding(2);
+      this.panel2.Name = "panel2";
+      this.panel2.Size = new System.Drawing.Size(705, 136);
+      this.panel2.TabIndex = 3;
       // 
       // lblPreviewColumnsVariance
@@ -542,18 +385,24 @@
       this.lblPreviewColumnsVariance.Dock = System.Windows.Forms.DockStyle.Left;
       this.lblPreviewColumnsVariance.Location = new System.Drawing.Point(0, 0);
-      this.lblPreviewColumnsVariance.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
       this.lblPreviewColumnsVariance.Name = "lblPreviewColumnsVariance";
-      this.lblPreviewColumnsVariance.Size = new System.Drawing.Size(398, 17);
+      this.lblPreviewColumnsVariance.Size = new System.Drawing.Size(301, 13);
       this.lblPreviewColumnsVariance.TabIndex = 2;
       this.lblPreviewColumnsVariance.Text = "{0} columns with a variance smaller than {1} would be deleted.";
       // 
+      // label12
+      // 
+      this.label12.AutoSize = true;
+      this.label12.Location = new System.Drawing.Point(6, 22);
+      this.label12.Name = "label12";
+      this.label12.Size = new System.Drawing.Size(0, 13);
+      this.label12.TabIndex = 2;
+      // 
       // tabPreviewDeleteRowsInfo
       // 
       this.tabPreviewDeleteRowsInfo.Controls.Add(this.lblPreviewRowsInfo);
       this.tabPreviewDeleteRowsInfo.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewDeleteRowsInfo.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.tabPreviewDeleteRowsInfo.Name = "tabPreviewDeleteRowsInfo";
-      this.tabPreviewDeleteRowsInfo.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewDeleteRowsInfo.Size = new System.Drawing.Size(951, 181);
+      this.tabPreviewDeleteRowsInfo.Padding = new System.Windows.Forms.Padding(3);
+      this.tabPreviewDeleteRowsInfo.Size = new System.Drawing.Size(711, 142);
       this.tabPreviewDeleteRowsInfo.TabIndex = 2;
       this.tabPreviewDeleteRowsInfo.Text = "del rows info";
@@ -563,54 +412,9 @@
       // 
       this.lblPreviewRowsInfo.AutoSize = true;
-      this.lblPreviewRowsInfo.Location = new System.Drawing.Point(4, 4);
-      this.lblPreviewRowsInfo.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+      this.lblPreviewRowsInfo.Location = new System.Drawing.Point(3, 3);
       this.lblPreviewRowsInfo.Name = "lblPreviewRowsInfo";
-      this.lblPreviewRowsInfo.Size = new System.Drawing.Size(400, 17);
+      this.lblPreviewRowsInfo.Size = new System.Drawing.Size(301, 13);
       this.lblPreviewRowsInfo.TabIndex = 2;
       this.lblPreviewRowsInfo.Text = "{0} rows with more than {1} % missing values would be deleted";
-      // 
-      // tabPreviewReplaceMissingValues
-      // 
-      this.tabPreviewReplaceMissingValues.Controls.Add(this.lblPreviewReplaceMissingValues);
-      this.tabPreviewReplaceMissingValues.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewReplaceMissingValues.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewReplaceMissingValues.Name = "tabPreviewReplaceMissingValues";
-      this.tabPreviewReplaceMissingValues.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewReplaceMissingValues.Size = new System.Drawing.Size(951, 181);
-      this.tabPreviewReplaceMissingValues.TabIndex = 6;
-      this.tabPreviewReplaceMissingValues.Text = "repl missing vals";
-      this.tabPreviewReplaceMissingValues.UseVisualStyleBackColor = true;
-      // 
-      // lblPreviewReplaceMissingValues
-      // 
-      this.lblPreviewReplaceMissingValues.AutoSize = true;
-      this.lblPreviewReplaceMissingValues.Location = new System.Drawing.Point(4, 4);
-      this.lblPreviewReplaceMissingValues.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.lblPreviewReplaceMissingValues.Name = "lblPreviewReplaceMissingValues";
-      this.lblPreviewReplaceMissingValues.Size = new System.Drawing.Size(449, 17);
-      this.lblPreviewReplaceMissingValues.TabIndex = 3;
-      this.lblPreviewReplaceMissingValues.Text = "{0} cells detected with missing values which would be replaced with {1}";
-      // 
-      // tabPreviewShuffle
-      // 
-      this.tabPreviewShuffle.Controls.Add(this.lblPreviewShuffle);
-      this.tabPreviewShuffle.Location = new System.Drawing.Point(4, 22);
-      this.tabPreviewShuffle.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewShuffle.Name = "tabPreviewShuffle";
-      this.tabPreviewShuffle.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
-      this.tabPreviewShuffle.Size = new System.Drawing.Size(951, 181);
-      this.tabPreviewShuffle.TabIndex = 4;
-      this.tabPreviewShuffle.Text = "shuffle";
-      this.tabPreviewShuffle.UseVisualStyleBackColor = true;
-      // 
-      // lblPreviewShuffle
-      // 
-      this.lblPreviewShuffle.AutoSize = true;
-      this.lblPreviewShuffle.Location = new System.Drawing.Point(4, 4);
-      this.lblPreviewShuffle.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
-      this.lblPreviewShuffle.Name = "lblPreviewShuffle";
-      this.lblPreviewShuffle.Size = new System.Drawing.Size(337, 17);
-      this.lblPreviewShuffle.TabIndex = 0;
-      this.lblPreviewShuffle.Text = "Data will be shuffled randomly - preview not possible";
       // 
       // label9
@@ -621,27 +425,7 @@
       this.label9.TabIndex = 0;
       // 
-      // panel1
-      // 
-      this.panel1.AutoScroll = true;
-      this.panel1.Controls.Add(this.lblPreviewColumnsInfo);
-      this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.panel1.Location = new System.Drawing.Point(4, 4);
-      this.panel1.Name = "panel1";
-      this.panel1.Size = new System.Drawing.Size(943, 173);
-      this.panel1.TabIndex = 2;
-      // 
-      // panel2
-      // 
-      this.panel2.AutoScroll = true;
-      this.panel2.Controls.Add(this.lblPreviewColumnsVariance);
-      this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
-      this.panel2.Location = new System.Drawing.Point(4, 4);
-      this.panel2.Name = "panel2";
-      this.panel2.Size = new System.Drawing.Size(943, 173);
-      this.panel2.TabIndex = 3;
-      // 
       // ManipulationView
       // 
-      this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F);
+      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
       this.Controls.Add(this.btnApply);
@@ -649,7 +433,6 @@
       this.Controls.Add(this.grpBoxData);
       this.Controls.Add(this.lstMethods);
-      this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
       this.Name = "ManipulationView";
-      this.Size = new System.Drawing.Size(985, 651);
+      this.Size = new System.Drawing.Size(739, 529);
       this.grpBoxData.ResumeLayout(false);
       this.tabsData.ResumeLayout(false);
@@ -662,8 +445,4 @@
       this.tabDataDeleteRowsInfo.ResumeLayout(false);
       this.tabDataDeleteRowsInfo.PerformLayout();
-      this.tabReplaceMissingValues.ResumeLayout(false);
-      this.tabReplaceMissingValues.PerformLayout();
-      this.tabDataShuffle.ResumeLayout(false);
-      this.tabDataShuffle.PerformLayout();
       this.grpBoxPreview.ResumeLayout(false);
       this.tabsPreview.ResumeLayout(false);
@@ -671,16 +450,12 @@
       this.tabPreviewInactive.PerformLayout();
       this.tabPreviewDeleteColumnsInfo.ResumeLayout(false);
+      this.panel1.ResumeLayout(false);
+      this.panel1.PerformLayout();
       this.tabPreviewDeleteColumnsVariance.ResumeLayout(false);
       this.tabPreviewDeleteColumnsVariance.PerformLayout();
+      this.panel2.ResumeLayout(false);
+      this.panel2.PerformLayout();
       this.tabPreviewDeleteRowsInfo.ResumeLayout(false);
       this.tabPreviewDeleteRowsInfo.PerformLayout();
-      this.tabPreviewReplaceMissingValues.ResumeLayout(false);
-      this.tabPreviewReplaceMissingValues.PerformLayout();
-      this.tabPreviewShuffle.ResumeLayout(false);
-      this.tabPreviewShuffle.PerformLayout();
-      this.panel1.ResumeLayout(false);
-      this.panel1.PerformLayout();
-      this.panel2.ResumeLayout(false);
-      this.panel2.PerformLayout();
       this.ResumeLayout(false);
 
@@ -697,6 +472,4 @@
     private System.Windows.Forms.TabPage tabPreviewDeleteColumnsVariance;
     private System.Windows.Forms.TabPage tabPreviewDeleteRowsInfo;
-    private System.Windows.Forms.TabPage tabPreviewShuffle;
-    private System.Windows.Forms.Label lblPreviewShuffle;
     private System.Windows.Forms.TabPage tabPreviewInactive;
     private System.Windows.Forms.Label lblPreviewColumnsInfo;
@@ -704,6 +477,4 @@
     private System.Windows.Forms.Label lblPreviewColumnsVariance;
     private System.Windows.Forms.Label lblPreviewRowsInfo;
-    private System.Windows.Forms.TabPage tabPreviewReplaceMissingValues;
-    private System.Windows.Forms.Label lblPreviewReplaceMissingValues;
     private System.Windows.Forms.Label label9;
     private System.Windows.Forms.TabControl tabsData;
@@ -721,15 +492,5 @@
     private System.Windows.Forms.TextBox txtDeleteRowsInfo;
     private System.Windows.Forms.Label label5;
-    private System.Windows.Forms.TabPage tabReplaceMissingValues;
-    private System.Windows.Forms.TextBox txtReplaceValue;
-    private System.Windows.Forms.ComboBox cmbReplaceWith;
-    private System.Windows.Forms.Label lblValueColon;
-    private System.Windows.Forms.Label label10;
-    private System.Windows.Forms.TabPage tabDataShuffle;
-    private System.Windows.Forms.Label lblShuffleProperties;
-    private System.Windows.Forms.ComboBox cmbVariableNames;
-    private System.Windows.Forms.Label label8;
     private System.Windows.Forms.Label lblPreviewInActive;
-    private System.Windows.Forms.CheckBox shuffleSeparatelyCheckbox;
     private System.Windows.Forms.Panel panel1;
     private System.Windows.Forms.Panel panel2;
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/ManipulationView.cs	(revision 15535)
@@ -21,5 +21,4 @@
 
 using System;
-using System.Collections.Generic;
 using System.Drawing;
 using System.Globalization;
@@ -44,5 +43,4 @@
     public ManipulationView() {
       InitializeComponent();
-      cmbReplaceWith.SelectedIndex = 0;
       tabsData.Appearance = TabAppearance.FlatButtons;
       tabsData.ItemSize = new Size(0, 1);
@@ -56,14 +54,10 @@
         () => ValidateDeleteColumnsVariance(),
         () => ValidateDeleteRowsInfo(),
-        () => ValidateReplaceWith(),
-        () => ValidateShuffle()
       };
 
       manipulations = new Action[] {
-        () => Content.ManipulationLogic.DeleteColumnsWithMissingValuesGreater(GetDeleteColumnsInfo()),
-        () => Content.ManipulationLogic.DeleteColumnsWithVarianceSmaller(GetDeleteColumnsVariance()),
-        () => Content.ManipulationLogic.DeleteRowsWithMissingValuesGreater(GetRowsColumnsInfo()),
-        () => ReplaceMissingValues(),
-        () => Content.ManipulationLogic.Shuffle(shuffleSeparatelyCheckbox.Checked)
+        () => Content.DeleteColumnsWithMissingValuesGreater(GetDeleteColumnsInfo()),
+        () => Content.DeleteColumnsWithVarianceSmaller(GetDeleteColumnsVariance()),
+        () => Content.DeleteRowsWithMissingValuesGreater(GetRowsColumnsInfo()),
       };
     }
@@ -72,9 +66,4 @@
       base.OnContentChanged();
       if (Content != null) {
-        cmbVariableNames.Items.Clear();
-        foreach (var name in Content.ManipulationLogic.VariableNames) {
-          cmbVariableNames.Items.Add(name);
-        }
-        cmbVariableNames.SelectedIndex = 0;
         CheckFilters();
       }
@@ -83,9 +72,9 @@
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
-      Content.FilterLogic.FilterChanged += FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged += FilterLogic_FilterChanged;
     }
 
     protected override void DeregisterContentEvents() {
-      Content.FilterLogic.FilterChanged -= FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged -= FilterLogic_FilterChanged;
       base.DeregisterContentEvents();
     }
@@ -98,5 +87,5 @@
 
     private void CheckFilters() {
-      if (Content.FilterLogic.IsFiltered) {
+      if (Content.PreprocessingData.IsFiltered) {
         tabsPreview.SelectedIndex = 0;
         lstMethods.Enabled = false;
@@ -126,36 +115,10 @@
     }
 
-    private void ReplaceMissingValues() {
-      var allIndices = Content.SearchLogic.GetMissingValueIndices();
-      var columnIndex = cmbVariableNames.SelectedIndex;
-      var columnIndices = new Dictionary<int, IList<int>>{
-          {columnIndex,   allIndices[columnIndex]}
-      };
-
-      switch (cmbReplaceWith.SelectedIndex) {
-        case 0: //Value
-          Content.ManipulationLogic.ReplaceIndicesByValue(columnIndices, txtReplaceValue.Text);
-          break;
-        case 1: //Average
-          Content.ManipulationLogic.ReplaceIndicesByAverageValue(columnIndices);
-          break;
-        case 2: //Median
-          Content.ManipulationLogic.ReplaceIndicesByMedianValue(columnIndices);
-          break;
-        case 3: //Most Common
-          Content.ManipulationLogic.ReplaceIndicesByMostCommonValue(columnIndices);
-          break;
-        case 4: //Random
-          Content.ManipulationLogic.ReplaceIndicesByRandomValue(columnIndices);
-          break;
-      }
-    }
-
     private void ValidateDeleteColumnsInfo() {
       ValidateDoubleTextBox(txtDeleteColumnsInfo.Text);
       if (btnApply.Enabled) {
-        var filteredColumns = Content.ManipulationLogic.ColumnsWithMissingValuesGreater(GetDeleteColumnsInfo());
+        var filteredColumns = Content.ColumnsWithMissingValuesGreater(GetDeleteColumnsInfo());
         int count = filteredColumns.Count;
-        int columnCount = Content.FilterLogic.PreprocessingData.Columns;
+        int columnCount = Content.PreprocessingData.Columns;
         lblPreviewColumnsInfo.Text = string.Format("{0} column{1} of {2} ({3}) were detected with more than {4}% missing values.", count, (count > 1 || count == 0 ? "s" : ""), columnCount, string.Format("{0:F2}%", 100d / columnCount * count), txtDeleteColumnsInfo.Text);
 
@@ -165,7 +128,7 @@
           sb.Append(Environment.NewLine);
           sb.Append("Columns: ");
-          sb.Append(Content.SearchLogic.VariableNames.ElementAt(filteredColumns.ElementAt(0)));
+          sb.Append(Content.PreprocessingData.VariableNames.ElementAt(filteredColumns.ElementAt(0)));
           for (int i = 1; i < filteredColumns.Count; i++) {
-            string columnName = Content.SearchLogic.VariableNames.ElementAt(filteredColumns.ElementAt(i));
+            string columnName = Content.PreprocessingData.VariableNames.ElementAt(filteredColumns.ElementAt(i));
             sb.Append(", ");
             sb.Append(columnName);
@@ -186,7 +149,7 @@
       ValidateDoubleTextBox(txtDeleteColumnsVariance.Text);
       if (btnApply.Enabled) {
-        var filteredColumns = Content.ManipulationLogic.ColumnsWithVarianceSmaller(GetDeleteColumnsVariance());
+        var filteredColumns = Content.ColumnsWithVarianceSmaller(GetDeleteColumnsVariance());
         int count = filteredColumns.Count;
-        int columnCount = Content.FilterLogic.PreprocessingData.Columns;
+        int columnCount = Content.PreprocessingData.Columns;
         lblPreviewColumnsVariance.Text = string.Format("{0} column{1} of {2} ({3}) were detected with a variance smaller than {4}.", count, (count > 1 || count == 0 ? "s" : ""), columnCount, string.Format("{0:F2}%", 100d / columnCount * count), txtDeleteColumnsVariance.Text);
 
@@ -196,7 +159,7 @@
           sb.Append(Environment.NewLine);
           sb.Append("Columns: ");
-          sb.Append(Content.SearchLogic.VariableNames.ElementAt(filteredColumns.ElementAt(0)));
+          sb.Append(Content.PreprocessingData.VariableNames.ElementAt(filteredColumns.ElementAt(0)));
           for (int i = 1; i < filteredColumns.Count; i++) {
-            string columnName = Content.SearchLogic.VariableNames.ElementAt(filteredColumns.ElementAt(i));
+            string columnName = Content.PreprocessingData.VariableNames.ElementAt(filteredColumns.ElementAt(i));
             sb.Append(", ");
             sb.Append(columnName);
@@ -217,6 +180,6 @@
       ValidateDoubleTextBox(txtDeleteRowsInfo.Text);
       if (btnApply.Enabled) {
-        int count = Content.ManipulationLogic.RowsWithMissingValuesGreater(GetRowsColumnsInfo()).Count;
-        int rowCount = Content.FilterLogic.PreprocessingData.Rows;
+        int count = Content.RowsWithMissingValuesGreater(GetRowsColumnsInfo()).Count;
+        int rowCount = Content.PreprocessingData.Rows;
         lblPreviewRowsInfo.Text = count + " row" + (count > 1 || count == 0 ? "s" : "") + " of " + rowCount + " (" + string.Format("{0:F2}%", 100d / rowCount * count) + ") were detected with more than " + txtDeleteRowsInfo.Text + "% missing values.";
         if (count > 0) {
@@ -228,45 +191,4 @@
         lblPreviewRowsInfo.Text = "Preview not possible yet - please input the limit above.";
       }
-    }
-
-    private void ValidateReplaceWith() {
-      btnApply.Enabled = false;
-      string replaceWith = (string)cmbReplaceWith.SelectedItem;
-      int columnIndex = cmbVariableNames.SelectedIndex;
-
-      if (cmbReplaceWith.SelectedIndex == 0) {
-        string errorMessage;
-        string replaceValue = txtReplaceValue.Text;
-        if (string.IsNullOrEmpty(replaceValue)) {
-          lblPreviewReplaceMissingValues.Text = "Preview not possible yet - please input the text which will be used as replacement.";
-        } else if (!Content.ManipulationLogic.PreProcessingData.Validate(txtReplaceValue.Text, out errorMessage, columnIndex)) {
-          lblPreviewReplaceMissingValues.Text = "Preview not possible yet - " + errorMessage;
-        } else {
-          btnApply.Enabled = true;
-        }
-        replaceWith = "\"" + replaceValue + "\"";
-      } else {
-        btnApply.Enabled = true;
-      }
-      if (btnApply.Enabled) {
-        var allIndices = Content.SearchLogic.GetMissingValueIndices();
-        int count = allIndices[columnIndex].Count;
-        int cellCount = Content.FilterLogic.PreprocessingData.Rows * Content.FilterLogic.PreprocessingData.Columns;
-        lblPreviewReplaceMissingValues.Text = count + " cell" + (count > 1 || count == 0 ? "s" : "")
-          + " of " + cellCount + " (" + string.Format("{0:F2}%", 100d / cellCount * count) + ") were detected with missing values which would be replaced with " + replaceWith;
-        if (count > 0) {
-          lblPreviewReplaceMissingValues.Text += Environment.NewLine + Environment.NewLine + "Please press the button \"Apply Manipulation\" if you wish to perform the replacement.";
-        } else {
-          btnApply.Enabled = false;
-        }
-      }
-    }
-
-    private void ValidateShuffle() {
-      btnApply.Enabled = true;
-      lblShuffleProperties.Enabled = false;
-      lblShuffleProperties.Visible = false;
-      shuffleSeparatelyCheckbox.Enabled = true;
-      shuffleSeparatelyCheckbox.Visible = true;
     }
 
@@ -295,12 +217,4 @@
           lblPreviewRowsInfo.Text = "rows successfully deleted.";
           break;
-        case 3:
-          lblPreviewReplaceMissingValues.Text = "missing values successfully replaced.";
-          btnApply.Enabled = false;
-          break;
-        case 4:
-          lblPreviewShuffle.Text = "dataset shuffled successfully.";
-          btnApply.Enabled = false;
-          break;
       }
     }
@@ -327,15 +241,4 @@
       ValidateDeleteRowsInfo();
     }
-
-    private void cmbReplaceWith_SelectedIndexChanged(object sender, EventArgs e) {
-      bool isReplaceWithValueSelected = cmbReplaceWith.SelectedIndex == 0;
-      lblValueColon.Visible = isReplaceWithValueSelected;
-      txtReplaceValue.Visible = isReplaceWithValueSelected;
-      ValidateReplaceWith();
-    }
-
-    private void txtReplaceValue_TextChanged(object sender, EventArgs e) {
-      ValidateReplaceWith();
-    }
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/StatisticsView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/StatisticsView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/StatisticsView.cs	(revision 15535)
@@ -87,11 +87,11 @@
 
     private void UpdateData(Dictionary<string, bool> oldVisibility = null) {
-      var logic = Content.StatisticsLogic;
-      rowsTextBox.Text = logic.GetRowCount().ToString();
-      columnsTextBox.Text = logic.GetColumnCount().ToString();
-      numericColumnsTextBox.Text = logic.GetNumericColumnCount().ToString();
-      nominalColumnsTextBox5.Text = logic.GetNominalColumnCount().ToString();
-      missingValuesTextBox.Text = logic.GetMissingValueCount().ToString();
-      totalValuesTextBox.Text = (logic.GetColumnCount() * logic.GetRowCount() - logic.GetMissingValueCount()).ToString();
+      var data = Content.PreprocessingData;
+      rowsTextBox.Text = data.Rows.ToString();
+      columnsTextBox.Text = data.Rows.ToString();
+      numericColumnsTextBox.Text = GetColumnCount<double>().ToString();
+      nominalColumnsTextBox5.Text = GetColumnCount<string>().ToString();
+      missingValuesTextBox.Text = data.GetMissingValueCount().ToString();
+      totalValuesTextBox.Text = (data.Rows * data.Rows - data.GetMissingValueCount()).ToString();
 
       var variableNames = Content.PreprocessingData.VariableNames.ToList();
@@ -107,11 +107,11 @@
         };
 
-      for (int i = 0; i < logic.GetColumnCount(); i++) {
-        var data = GetStatistics(i);
-        for (int j = 0; j < data.Count; j++) {
+      for (int i = 0; i < data.Columns; i++) {
+        var statistics = GetStatistics(i);
+        for (int j = 0; j < statistics.Count; j++) {
           if (horizontal)
-            statisticsMatrix[j, i] = data[j];
+            statisticsMatrix[j, i] = statistics[j];
           else
-            statisticsMatrix[i, j] = data[j];
+            statisticsMatrix[i, j] = statistics[j];
         }
       }
@@ -138,12 +138,22 @@
     }
 
+    public int GetColumnCount<T>() {
+      int count = 0;
+      for (int i = 0; i < Content.PreprocessingData.Columns; ++i) {
+        if (Content.PreprocessingData.VariableHasType<T>(i)) {
+          ++count;
+        }
+      }
+      return count;
+    }
+
     private List<string> GetStatistics(int varIdx) {
       List<string> list;
-      var logic = Content.StatisticsLogic;
-      if (logic.VariableHasType<double>(varIdx)) {
+      var data = Content.PreprocessingData;
+      if (data.VariableHasType<double>(varIdx)) {
         list = GetDoubleColumns(varIdx);
-      } else if (logic.VariableHasType<string>(varIdx)) {
+      } else if (data.VariableHasType<string>(varIdx)) {
         list = GetStringColumns(varIdx);
-      } else if (logic.VariableHasType<DateTime>(varIdx)) {
+      } else if (data.VariableHasType<DateTime>(varIdx)) {
         list = GetDateTimeColumns(varIdx);
       } else {
@@ -157,54 +167,54 @@
 
     private List<string> GetDoubleColumns(int statIdx) {
-      var logic = Content.StatisticsLogic;
+      var data = Content.PreprocessingData;
       return new List<string> {
-        logic.GetColumnTypeAsString(statIdx),
-        logic.GetMissingValueCount(statIdx).ToString(),
-        logic.GetMin<double>(statIdx, double.NaN).ToString(),
-        logic.GetMax<double>(statIdx, double.NaN).ToString(),
-        logic.GetMedian(statIdx).ToString(),
-        logic.GetAverage(statIdx).ToString(),
-        logic.GetStandardDeviation(statIdx).ToString(),
-        logic.GetVariance(statIdx).ToString(),
-        logic.GetOneQuarterPercentile(statIdx).ToString(),
-        logic.GetThreeQuarterPercentile(statIdx).ToString(),
-        logic.GetMostCommonValue<double>(statIdx, double.NaN).ToString(),
-        logic.GetDifferentValuesCount<double>(statIdx).ToString()
+        data.GetVariableType(statIdx).Name,
+        data.GetMissingValueCount(statIdx).ToString(),
+        data.GetMin<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetMax<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetMedian<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetMean<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetStandardDeviation<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetVariance<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetQuantile<double>(0.25, statIdx, emptyValue: double.NaN).ToString(),
+        data.GetQuantile<double>(0.75, statIdx, emptyValue: double.NaN).ToString(),
+        data.GetMode<double>(statIdx, emptyValue: double.NaN).ToString(),
+        data.GetDistinctValues<double>(statIdx).ToString()
       };
     }
 
     private List<string> GetStringColumns(int statIdx) {
-      var logic = Content.StatisticsLogic;
+      var data = Content.PreprocessingData;
       return new List<string> {
-        logic.GetColumnTypeAsString(statIdx),
-        logic.GetMissingValueCount(statIdx).ToString(),
-        "", //min
-        "", //max
-        "", //median
+        data.GetVariableType(statIdx).Name,
+        data.GetMissingValueCount(statIdx).ToString(),
+        "", // data.GetMin<string>(statIdx, emptyValue: string.Empty), //min
+        "", // data.GetMax<string>(statIdx, emptyValue: string.Empty), //max
+        "", // data.GetMedian<string>(statIdx, emptyValue: string.Empty), //median
         "", //average
         "", //standard deviation
         "", //variance
-        "", //quarter percentile
-        "", //three quarter percentile
-        logic.GetMostCommonValue<string>(statIdx,string.Empty) ?? "",
-        logic.GetDifferentValuesCount<string>(statIdx).ToString()
+        "", // data.GetQuantile<string>(0.25, statIdx, emptyValue: string.Empty), //quarter percentile
+        "", // data.GetQuantile<string>(0.75, statIdx, emptyValue: string.Empty), //three quarter percentile
+        data.GetMode<string>(statIdx, emptyValue: string.Empty),
+        data.GetDistinctValues<string>(statIdx).ToString()
       };
     }
 
     private List<string> GetDateTimeColumns(int statIdx) {
-      var logic = Content.StatisticsLogic;
+      var data = Content.PreprocessingData;
       return new List<string> {
-        logic.GetColumnTypeAsString(statIdx),
-        logic.GetMissingValueCount(statIdx).ToString(),
-        logic.GetMin<DateTime>(statIdx, DateTime.MinValue).ToString(),
-        logic.GetMax<DateTime>(statIdx, DateTime.MinValue).ToString(),
-        logic.GetMedianDateTime(statIdx).ToString(),
-        logic.GetAverageDateTime(statIdx).ToString(),
-        logic.GetStandardDeviation(statIdx).ToString(),
-        logic.GetVariance(statIdx).ToString(),
-        logic.GetOneQuarterPercentile(statIdx).ToString(),
-        logic.GetThreeQuarterPercentile(statIdx).ToString(),
-        logic.GetMostCommonValue<DateTime>(statIdx, DateTime.MinValue).ToString(),
-        logic.GetDifferentValuesCount<DateTime>(statIdx).ToString()
+        data.GetVariableType(statIdx).Name,
+        data.GetMissingValueCount(statIdx).ToString(),
+        data.GetMin<DateTime>(statIdx).ToString(),
+        data.GetMax<DateTime>(statIdx).ToString(),
+        data.GetMedian<DateTime>(statIdx).ToString(),
+        data.GetMean<DateTime>(statIdx).ToString(),
+        "", // should be of type TimeSpan //data.GetStandardDeviation<DateTime>(statIdx).ToString(),
+        "", // should be of type TimeSpan //data.GetVariance<DateTime>(statIdx).ToString(),
+        data.GetQuantile<DateTime>(0.25, statIdx).ToString(),
+        data.GetQuantile<DateTime>(0.75, statIdx).ToString(),
+        data.GetMode<DateTime>(statIdx).ToString(),
+        data.GetDistinctValues<DateTime>(statIdx).ToString()
       };
     }
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/TransformationView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/TransformationView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/TransformationView.cs	(revision 15535)
@@ -51,9 +51,9 @@
 
     protected override void RegisterContentEvents() {
-      Content.FilterLogic.FilterChanged += FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged += FilterLogic_FilterChanged;
     }
 
     protected override void DeregisterContentEvents() {
-      Content.FilterLogic.FilterChanged -= FilterLogic_FilterChanged;
+      Content.PreprocessingData.FilterChanged -= FilterLogic_FilterChanged;
     }
 
@@ -65,5 +65,5 @@
 
     private void CheckFilters() {
-      if (Content.FilterLogic.IsFiltered) {
+      if (Content.PreprocessingData.IsFiltered) {
         applyButton.Enabled = false;
         lblFilterNotice.Visible = true;
@@ -82,5 +82,5 @@
       }
 
-      var transformator = new PreprocessingTransformator(Content.Data);
+      var transformator = new PreprocessingTransformator(Content.PreprocessingData);
       bool preserve = preserveColumnsCheckbox.CheckState == CheckState.Checked;
       string errorMsg;
Index: /stable/HeuristicLab.DataPreprocessing.Views/3.4/ViewShortcutListView.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing.Views/3.4/ViewShortcutListView.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing.Views/3.4/ViewShortcutListView.cs	(revision 15535)
@@ -42,18 +42,16 @@
     //Clone chart items
     protected override void itemsListView_DoubleClick(object sender, EventArgs e) {
-      if (itemsListView.SelectedItems.Count == 1) {
-        IViewShortcut item = itemsListView.SelectedItems[0].Tag as IViewShortcut;
-        if (item != null) {
-          try {
-            item = (IViewShortcut)item.Clone();
-            var view = MainFormManager.MainForm.ShowContent(item);
-            if (view != null) {
-              view.ReadOnly = ReadOnly;
-              view.Locked = Locked;
-            }
-          } catch (NullReferenceException) {
-            // cloning for preprocessing not done properly yet
-          }
+      if (itemsListView.SelectedItems.Count != 1) return;
+      IViewShortcut item = itemsListView.SelectedItems[0].Tag as IViewShortcut;
+      if (item == null) return;
+      try {
+        item = (IViewShortcut)item.Clone();
+        var view = MainFormManager.MainForm.ShowContent(item);
+        if (view != null) {
+          view.ReadOnly = ReadOnly;
+          view.Locked = Locked;
         }
+      } catch (NullReferenceException) {
+        // cloning for preprocessing not done properly yet
       }
     }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 15535)
@@ -23,17 +23,18 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Feature Correlation Matrix", "Represents the feature correlation matrix.")]
-  public class CorrelationMatrixContent : Item, IViewShortcut {
+  [StorableClass]
+  public class CorrelationMatrixContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Gradient; }
     }
 
+    [Storable]
     public PreprocessingContext Context { get; private set; }
-    public ITransactionalPreprocessingData PreprocessingData {
-      get { return Context.Data; }
-    }
+
 
     public DataAnalysisProblemData ProblemData {
@@ -47,5 +48,7 @@
     }
 
-    public CorrelationMatrixContent(PreprocessingContext context) {
+    #region Constructor, Cloning & Persistence
+    public CorrelationMatrixContent(PreprocessingContext context)
+      : base(context.Data) {
       Context = context;
     }
@@ -55,8 +58,12 @@
       Context = original.Context;
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new CorrelationMatrixContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected CorrelationMatrixContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
 
     public event DataPreprocessingChangedEventHandler Changed {
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 15535)
@@ -23,27 +23,30 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Data Completeness Chart", "Represents a datacompleteness chart.")]
-
-  public class DataCompletenessChartContent : Item, IViewShortcut {
+  [StorableClass]
+  public class DataCompletenessChartContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.EditBrightnessContrast; }
     }
 
-    public SearchLogic SearchLogic { get; private set; }
-
-    public DataCompletenessChartContent(SearchLogic searchLogic) {
-      SearchLogic = searchLogic;
+    #region Constructor, Cloning & Persistence
+    public DataCompletenessChartContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
     }
 
     public DataCompletenessChartContent(DataCompletenessChartContent content, Cloner cloner)
       : base(content, cloner) {
-      SearchLogic = content.SearchLogic;
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new DataCompletenessChartContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected DataCompletenessChartContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 15535)
@@ -27,30 +27,27 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+using HeuristicLab.Random;
 
 namespace HeuristicLab.DataPreprocessing {
-
   [Item("Data Grid", "Represents a data grid.")]
-  public class DataGridContent : Item, IStringConvertibleMatrix, IViewShortcut {
+  [StorableClass]
+  public class DataGridContent : PreprocessingContent, IStringConvertibleMatrix, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Table; }
     }
 
-    public ITransactionalPreprocessingData PreProcessingData { get; private set; }
-
-    public ManipulationLogic ManipulationLogic { get; private set; }
-    public FilterLogic FilterLogic { get; private set; }
-
     public int Rows {
-      get { return PreProcessingData.Rows; }
+      get { return PreprocessingData.Rows; }
       set { }
     }
 
     public int Columns {
-      get { return PreProcessingData.Columns; }
+      get { return PreprocessingData.Columns; }
       set { }
     }
 
     public IEnumerable<string> ColumnNames {
-      get { return PreProcessingData.VariableNames; }
+      get { return PreprocessingData.VariableNames; }
       set { }
     }
@@ -71,17 +68,15 @@
 
     public IDictionary<int, IList<int>> Selection {
-      get { return PreProcessingData.Selection; }
-      set { PreProcessingData.Selection = value; }
-    }
-
-    public DataGridContent(ITransactionalPreprocessingData preProcessingData, ManipulationLogic theManipulationLogic, FilterLogic theFilterLogic) {
-      ManipulationLogic = theManipulationLogic;
-      FilterLogic = theFilterLogic;
-      PreProcessingData = preProcessingData;
-    }
-
-    public DataGridContent(DataGridContent dataGridContent, Cloner cloner)
-      : base(dataGridContent, cloner) {
-
+      get { return PreprocessingData.Selection; }
+      set { PreprocessingData.Selection = value; }
+    }
+
+    #region Constructor, Cloning & Persistence
+    public DataGridContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
+    }
+
+    public DataGridContent(DataGridContent original, Cloner cloner)
+      : base(original, cloner) {
     }
     public override IDeepCloneable Clone(Cloner cloner) {
@@ -89,27 +84,32 @@
     }
 
+    [StorableConstructor]
+    protected DataGridContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+
     public void DeleteRows(IEnumerable<int> rows) {
-      PreProcessingData.DeleteRowsWithIndices(rows);
+      PreprocessingData.DeleteRowsWithIndices(rows);
     }
 
     public void DeleteColumn(int column) {
-      PreProcessingData.DeleteColumn(column);
+      PreprocessingData.DeleteColumn(column);
     }
 
     public bool Validate(string value, out string errorMessage, int columnIndex) {
-      return PreProcessingData.Validate(value, out errorMessage, columnIndex);
+      return PreprocessingData.Validate(value, out errorMessage, columnIndex);
     }
 
     public string GetValue(int rowIndex, int columnIndex) {
-      return PreProcessingData.GetCellAsString(columnIndex, rowIndex);
+      return PreprocessingData.GetCellAsString(columnIndex, rowIndex);
     }
 
     public bool SetValue(string value, int rowIndex, int columnIndex) {
-      return PreProcessingData.SetValue(value, columnIndex, rowIndex);
+      return PreprocessingData.SetValue(value, columnIndex, rowIndex);
     }
 
     public event DataPreprocessingChangedEventHandler Changed {
-      add { PreProcessingData.Changed += value; }
-      remove { PreProcessingData.Changed -= value; }
+      add { PreprocessingData.Changed += value; }
+      remove { PreprocessingData.Changed -= value; }
     }
 
@@ -132,4 +132,217 @@
 #pragma warning restore 0067
     #endregion
+
+    #region Manipulations
+    private void ReplaceIndicesByValue(IDictionary<int, IList<int>> cells, Func<int, double> doubleAggregator = null,
+      Func<int, DateTime> dateTimeAggregator = null, Func<int, string> stringAggregator = null) {
+      PreprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          if (doubleAggregator != null && PreprocessingData.VariableHasType<double>(column.Key)) {
+            var value = doubleAggregator(column.Key);
+            foreach (int index in column.Value)
+              PreprocessingData.SetCell<double>(column.Key, index, value);
+          } else if (dateTimeAggregator != null && PreprocessingData.VariableHasType<DateTime>(column.Key)) {
+            var value = dateTimeAggregator(column.Key);
+            foreach (int index in column.Value)
+              PreprocessingData.SetCell<DateTime>(column.Key, index, value);
+          } else if (stringAggregator != null && PreprocessingData.VariableHasType<string>(column.Key)) {
+            var value = stringAggregator(column.Key);
+            foreach (int index in column.Value)
+              PreprocessingData.SetCell<string>(column.Key, index, value);
+          }
+        }
+      });
+    }
+
+    private void ReplaceIndicesByValues(IDictionary<int, IList<int>> cells, Func<int, IEnumerable<double>> doubleAggregator = null,
+      Func<int, IEnumerable<DateTime>> dateTimeAggregator = null, Func<int, IEnumerable<string>> stringAggregator = null) {
+      PreprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          if (doubleAggregator != null && PreprocessingData.VariableHasType<double>(column.Key)) {
+            var values = doubleAggregator(column.Key);
+            foreach (var pair in column.Value.Zip(values, (row, value) => new { row, value }))
+              PreprocessingData.SetCell<double>(column.Key, pair.row, pair.value);
+          } else if (dateTimeAggregator != null && PreprocessingData.VariableHasType<DateTime>(column.Key)) {
+            var values = dateTimeAggregator(column.Key);
+            foreach (var pair in column.Value.Zip(values, (row, value) => new { row, value }))
+              PreprocessingData.SetCell<DateTime>(column.Key, pair.row, pair.value);
+          } else if (stringAggregator != null && PreprocessingData.VariableHasType<string>(column.Key)) {
+            var values = stringAggregator(column.Key);
+            foreach (var pair in column.Value.Zip(values, (row, value) => new { row, value }))
+              PreprocessingData.SetCell<string>(column.Key, pair.row, pair.value);
+          }
+        }
+      });
+    }
+
+    public void ReplaceIndicesByMean(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      ReplaceIndicesByValue(cells,
+        col => PreprocessingData.GetMean<double>(col, considerSelection),
+        col => PreprocessingData.GetMean<DateTime>(col, considerSelection));
+    }
+
+    public void ReplaceIndicesByMedianValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      ReplaceIndicesByValue(cells,
+        col => PreprocessingData.GetMedian<double>(col, considerSelection),
+        col => PreprocessingData.GetMedian<DateTime>(col, considerSelection));
+    }
+
+    public void ReplaceIndicesByMode(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      ReplaceIndicesByValue(cells,
+        col => PreprocessingData.GetMode<double>(col, considerSelection),
+        col => PreprocessingData.GetMode<DateTime>(col, considerSelection),
+        col => PreprocessingData.GetMode<string>(col, considerSelection));
+    }
+
+    public void ReplaceIndicesByRandomValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      var rand = new FastRandom();
+      ReplaceIndicesByValues(cells,
+        col => {
+          double min = PreprocessingData.GetMin<double>(col, considerSelection);
+          double max = PreprocessingData.GetMax<double>(col, considerSelection);
+          double range = max - min;
+          return cells[col].Select(_ => rand.NextDouble() * range + min);
+        },
+        col => {
+          var min = PreprocessingData.GetMin<DateTime>(col, considerSelection);
+          var max = PreprocessingData.GetMax<DateTime>(col, considerSelection);
+          double range = (max - min).TotalSeconds;
+          return cells[col].Select(_ => min + TimeSpan.FromSeconds(rand.NextDouble() * range));
+        });
+    }
+
+    public void ReplaceIndicesByString(IDictionary<int, IList<int>> cells, string value) {
+      PreprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          foreach (var rowIdx in column.Value) {
+            PreprocessingData.SetValue(value, column.Key, rowIdx);
+          }
+        }
+      });
+    }
+
+
+    public void ReplaceIndicesByLinearInterpolationOfNeighbours(IDictionary<int, IList<int>> cells) {
+      PreprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          IList<Tuple<int, int>> startEndings = GetStartAndEndingsForInterpolation(column);
+          foreach (var tuple in startEndings) {
+            Interpolate(column, tuple.Item1, tuple.Item2);
+          }
+        }
+      });
+    }
+
+    private List<Tuple<int, int>> GetStartAndEndingsForInterpolation(KeyValuePair<int, IList<int>> column) {
+      var startEndings = new List<Tuple<int, int>>();
+      var rowIndices = column.Value.OrderBy(x => x).ToList();
+      var count = rowIndices.Count;
+      int start = int.MinValue;
+      for (int i = 0; i < count; ++i) {
+        if (start == int.MinValue) {
+          start = IndexOfPrevPresentValue(column.Key, rowIndices[i]);
+        }
+        if (i + 1 == count || (i + 1 < count && rowIndices[i + 1] - rowIndices[i] > 1)) {
+          int next = IndexOfNextPresentValue(column.Key, rowIndices[i]);
+          if (start > 0 && next < PreprocessingData.Rows) {
+            startEndings.Add(new Tuple<int, int>(start, next));
+          }
+          start = int.MinValue;
+        }
+      }
+      return startEndings;
+    }
+
+    private void Interpolate(KeyValuePair<int, IList<int>> column, int prevIndex, int nextIndex) {
+      int valuesToInterpolate = nextIndex - prevIndex;
+
+      if (PreprocessingData.VariableHasType<double>(column.Key)) {
+        double prev = PreprocessingData.GetCell<double>(column.Key, prevIndex);
+        double next = PreprocessingData.GetCell<double>(column.Key, nextIndex);
+        double interpolationStep = (next - prev) / valuesToInterpolate;
+
+        for (int i = prevIndex; i < nextIndex; ++i) {
+          double interpolated = prev + (interpolationStep * (i - prevIndex));
+          PreprocessingData.SetCell<double>(column.Key, i, interpolated);
+        }
+      } else if (PreprocessingData.VariableHasType<DateTime>(column.Key)) {
+        DateTime prev = PreprocessingData.GetCell<DateTime>(column.Key, prevIndex);
+        DateTime next = PreprocessingData.GetCell<DateTime>(column.Key, nextIndex);
+        double interpolationStep = (next - prev).TotalSeconds / valuesToInterpolate;
+
+        for (int i = prevIndex; i < nextIndex; ++i) {
+          DateTime interpolated = prev.AddSeconds(interpolationStep * (i - prevIndex));
+          PreprocessingData.SetCell<DateTime>(column.Key, i, interpolated);
+        }
+      }
+    }
+
+    private int IndexOfPrevPresentValue(int columnIndex, int start) {
+      int offset = start - 1;
+      while (offset >= 0 && PreprocessingData.IsCellEmpty(columnIndex, offset)) {
+        offset--;
+      }
+
+      return offset;
+    }
+
+    private int IndexOfNextPresentValue(int columnIndex, int start) {
+      int offset = start + 1;
+      while (offset < PreprocessingData.Rows && PreprocessingData.IsCellEmpty(columnIndex, offset)) {
+        offset++;
+      }
+
+      return offset;
+    }
+
+    public void Shuffle(bool shuffleRangesSeparately) {
+      var random = new FastRandom();
+
+      if (shuffleRangesSeparately) {
+        var ranges = new[] { PreprocessingData.TestPartition, PreprocessingData.TrainingPartition };
+        PreprocessingData.InTransaction(() => {
+          // process all given ranges - e.g. TrainingPartition, TestPartition
+          foreach (IntRange range in ranges) {
+            var indices = Enumerable.Range(0, PreprocessingData.Rows).ToArray();
+            var shuffledIndices = Enumerable.Range(range.Start, range.Size).Shuffle(random).ToArray();
+            for (int i = range.Start, j = 0; i < range.End; i++, j++)
+              indices[i] = shuffledIndices[j];
+
+            ReOrderToIndices(indices);
+          }
+        });
+
+      } else {
+        PreprocessingData.InTransaction(() => {
+          var indices = Enumerable.Range(0, PreprocessingData.Rows).ToArray();
+          indices.ShuffleInPlace(random);
+          ReOrderToIndices(indices);
+        });
+      }
+    }
+
+    public void ReOrderToIndices(int[] indices) {
+      PreprocessingData.InTransaction(() => {
+        for (int i = 0; i < PreprocessingData.Columns; ++i) {
+          if (PreprocessingData.VariableHasType<double>(i))
+            ReOrderToIndices<double>(i, indices);
+          else if (PreprocessingData.VariableHasType<string>(i))
+            ReOrderToIndices<string>(i, indices);
+          else if (PreprocessingData.VariableHasType<DateTime>(i))
+            ReOrderToIndices<DateTime>(i, indices);
+        }
+      });
+    }
+
+    private void ReOrderToIndices<T>(int columnIndex, int[] indices) {
+      var originalData = new List<T>(PreprocessingData.GetValues<T>(columnIndex));
+      if (indices.Length != originalData.Count) throw new InvalidOperationException("The number of provided indices does not match the values.");
+
+      for (int i = 0; i < indices.Length; i++) {
+        T newValue = originalData[indices[i]];
+        PreprocessingData.SetCell<T>(columnIndex, i, newValue);
+      }
+    }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs	(revision 15535)
@@ -20,35 +20,70 @@
 #endregion
 
+using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.DataPreprocessing.Filter;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Filter", "Represents the filter grid.")]
-  public class FilterContent : Item, IViewShortcut {
+  [StorableClass]
+  public class FilterContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Filter; }
     }
-
-    public FilterLogic FilterLogic { get; private set; }
-
+    [Storable]
     public ICheckedItemCollection<IFilter> Filters { get; private set; }
 
+    [Storable]
     public bool IsAndCombination { get; set; }
 
-    public FilterContent(FilterLogic filterLogic) {
+    public IEnumerable<IFilter> ActiveFilters {
+      get { return Filters.Where(f => f.Active && f.ConstraintData != null); }
+    }
+
+    public bool[] GetRemainingRows() {
+      var remainingRows = new bool[PreprocessingData.Rows];
+      if (ActiveFilters.Any()) {
+        var filterResults = ActiveFilters.Select(f => f.Check()).ToList();
+        var rowFilterResults = new bool[filterResults.Count];
+        for (int row = 0; row < remainingRows.Length; row++) {
+          for (int i = 0; i < filterResults.Count; i++)
+            rowFilterResults[i] = filterResults[i][row];
+
+          remainingRows[row] = IsAndCombination
+            ? rowFilterResults.All(x => x)
+            : rowFilterResults.Any(x => x);
+        }
+      } else {
+        // if not filters active => all rows are remaining
+        for (int i = 0; i < remainingRows.Length; i++)
+          remainingRows[i] = true;
+      }
+      return remainingRows;
+    }
+
+    #region Constructor, Cloning & Persistence
+    public FilterContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
       Filters = new CheckedItemCollection<IFilter>();
       IsAndCombination = true;
-      FilterLogic = filterLogic;
     }
 
-    protected FilterContent(FilterContent content, Cloner cloner)
-      : base(content, cloner) {
+    protected FilterContent(FilterContent original, Cloner cloner)
+      : base(original, cloner) {
+      Filters = cloner.Clone(original.Filters);
+      IsAndCombination = original.IsAndCombination;
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new FilterContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected FilterContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs	(revision 15535)
@@ -26,7 +26,9 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Histogram", "Represents the histogram grid.")]
+  [StorableClass]
   public class HistogramContent : PreprocessingChartContent {
     public static new Image StaticItemImage {
@@ -34,11 +36,16 @@
     }
 
+    [Storable]
     public string GroupingVariableName { get; set; }
 
+    [Storable]
     public int Bins { get; set; }
+    [Storable]
     public bool ExactBins { get; set; }
 
+    [Storable]
     public LegendOrder Order { get; set; }
 
+    #region Constructor, Cloning & Persistence
     public HistogramContent(IFilteredPreprocessingData preprocessingData)
       : base(preprocessingData) {
@@ -47,10 +54,19 @@
     }
 
-    public HistogramContent(HistogramContent content, Cloner cloner)
-      : base(content, cloner) {
+    public HistogramContent(HistogramContent original, Cloner cloner)
+      : base(original, cloner) {
+      GroupingVariableName = original.GroupingVariableName;
+      Bins = original.Bins;
+      ExactBins = original.ExactBins;
+      Order = original.Order;
     }
     public override IDeepCloneable Clone(Cloner cloner) {
       return new HistogramContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected HistogramContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
 
     public static DataTable CreateHistogram(IFilteredPreprocessingData preprocessingData, string variableName, string groupingVariableName, DataTableVisualProperties.DataTableHistogramAggregation aggregation, LegendOrder legendOrder = LegendOrder.Alphabetically) {
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs	(revision 15535)
@@ -23,15 +23,19 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
-
   [Item("Line Chart", "Represents the line chart grid.")]
+  [StorableClass]
   public class LineChartContent : PreprocessingChartContent {
-    public bool AllInOneMode { get; set; }
-
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
     }
 
+    [Storable]
+    public bool AllInOneMode { get; set; }
+
+
+    #region Constructor, Cloning & Persistence
     public LineChartContent(IFilteredPreprocessingData preprocessingData)
       : base(preprocessingData) {
@@ -39,11 +43,16 @@
     }
 
-    public LineChartContent(LineChartContent content, Cloner cloner)
-      : base(content, cloner) {
-      this.AllInOneMode = content.AllInOneMode;
+    public LineChartContent(LineChartContent original, Cloner cloner)
+      : base(original, cloner) {
+      AllInOneMode = original.AllInOneMode;
     }
     public override IDeepCloneable Clone(Cloner cloner) {
       return new LineChartContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected LineChartContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs	(revision 15535)
@@ -20,31 +20,107 @@
 #endregion
 
+using System;
+using System.Collections.Generic;
 using System.Drawing;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
-
   [Item("Manipulation", "Represents the available manipulations on a data set.")]
-  public class ManipulationContent : Item, IViewShortcut {
+  [StorableClass]
+  public class ManipulationContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
     }
 
-    public ManipulationLogic ManipulationLogic { get; private set; }
-    public SearchLogic SearchLogic { get; private set; }
-    public FilterLogic FilterLogic { get; private set; }
-
-    public ManipulationContent(ManipulationLogic manipulationLogic, SearchLogic searchLogic, FilterLogic filterLogic) {
-      ManipulationLogic = manipulationLogic;
-      SearchLogic = searchLogic;
-      FilterLogic = filterLogic;
+    #region Constructor, Cloning & Persistence
+    public ManipulationContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
     }
 
-    public ManipulationContent(ManipulationContent content, Cloner cloner) : base(content, cloner) { }
-
+    public ManipulationContent(ManipulationContent original, Cloner cloner) :
+      base(original, cloner) {
+    }
     public override IDeepCloneable Clone(Cloner cloner) {
       return new ManipulationContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected ManipulationContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+
+    public List<int> RowsWithMissingValuesGreater(double percent) {
+      List<int> rows = new List<int>();
+
+      for (int i = 0; i < PreprocessingData.Rows; ++i) {
+        int missingCount = PreprocessingData.GetRowMissingValueCount(i);
+        if (100f / PreprocessingData.Columns * missingCount > percent) {
+          rows.Add(i);
+        }
+      }
+
+      return rows;
+    }
+
+    public List<int> ColumnsWithMissingValuesGreater(double percent) {
+      List<int> columns = new List<int>();
+      for (int i = 0; i < PreprocessingData.Columns; ++i) {
+        int missingCount = PreprocessingData.GetMissingValueCount(i);
+        if (100f / PreprocessingData.Rows * missingCount > percent) {
+          columns.Add(i);
+        }
+      }
+
+      return columns;
+    }
+
+    public List<int> ColumnsWithVarianceSmaller(double variance) {
+      List<int> columns = new List<int>();
+      for (int i = 0; i < PreprocessingData.Columns; ++i) {
+        if (PreprocessingData.VariableHasType<double>(i)) {
+          double columnVariance = PreprocessingData.GetVariance<double>(i);
+          if (columnVariance < variance) {
+            columns.Add(i);
+          }
+        } else if (PreprocessingData.VariableHasType<DateTime>(i)) {
+          double columnVariance = (double)PreprocessingData.GetVariance<DateTime>(i).Ticks / TimeSpan.TicksPerSecond;
+          if (columnVariance < variance) {
+            columns.Add(i);
+          }
+        }
+      }
+      return columns;
+    }
+
+    public void DeleteRowsWithMissingValuesGreater(double percent) {
+      DeleteRows(RowsWithMissingValuesGreater(percent));
+    }
+
+    public void DeleteColumnsWithMissingValuesGreater(double percent) {
+      DeleteColumns(ColumnsWithMissingValuesGreater(percent));
+    }
+
+    public void DeleteColumnsWithVarianceSmaller(double variance) {
+      DeleteColumns(ColumnsWithVarianceSmaller(variance));
+    }
+
+    private void DeleteRows(List<int> rows) {
+      PreprocessingData.InTransaction(() => {
+        foreach (int row in rows.OrderByDescending(x => x)) {
+          PreprocessingData.DeleteRow(row);
+        }
+      });
+    }
+
+    private void DeleteColumns(List<int> columns) {
+      PreprocessingData.InTransaction(() => {
+        foreach (int column in columns.OrderByDescending(x => x)) {
+          PreprocessingData.DeleteColumn(column);
+        }
+      });
+    }
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/MultiScatterPlotContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/MultiScatterPlotContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/MultiScatterPlotContent.cs	(revision 15535)
@@ -23,8 +23,9 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
-
   [Item("Multi Scatter Plot", "Represents a multi scatter plot.")]
+  [StorableClass]
   public class MultiScatterPlotContent : ScatterPlotContent {
     public static new Image StaticItemImage {
@@ -32,15 +33,20 @@
     }
 
+    #region Constructor, Cloning & Persistence
     public MultiScatterPlotContent(IFilteredPreprocessingData preprocessingData)
       : base(preprocessingData) {
     }
 
-    public MultiScatterPlotContent(MultiScatterPlotContent content, Cloner cloner)
-      : base(content, cloner) {
+    public MultiScatterPlotContent(MultiScatterPlotContent original, Cloner cloner)
+      : base(original, cloner) {
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new MultiScatterPlotContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected MultiScatterPlotContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs	(revision 15535)
@@ -29,8 +29,10 @@
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("PreprocessingChart", "Represents a preprocessing chart.")]
-  public class PreprocessingChartContent : Item, IViewShortcut {
+  [StorableClass]
+  public class PreprocessingChartContent : PreprocessingContent, IViewShortcut {
     public enum LegendOrder {
       Alphabetically,
@@ -42,14 +44,14 @@
     }
 
-    private ICheckedItemList<StringValue> variableItemList = null;
+    [Storable]
+    private ICheckedItemList<StringValue> variableItemList;
     public ICheckedItemList<StringValue> VariableItemList {
       get {
         if (variableItemList == null)
           variableItemList = CreateVariableItemList(PreprocessingData);
-        return this.variableItemList;
+        return variableItemList;
       }
     }
 
-    public IFilteredPreprocessingData PreprocessingData { get; private set; }
     public event DataPreprocessingChangedEventHandler Changed {
       add { PreprocessingData.Changed += value; }
@@ -57,16 +59,21 @@
     }
 
-    public PreprocessingChartContent(IFilteredPreprocessingData preprocessingData) {
-      PreprocessingData = preprocessingData;
+    #region Constructor, Cloning & Persistence
+    public PreprocessingChartContent(IFilteredPreprocessingData preprocessingData)
+       : base(preprocessingData) {
     }
 
-    public PreprocessingChartContent(PreprocessingChartContent content, Cloner cloner)
-      : base(content, cloner) {
-      this.PreprocessingData = content.PreprocessingData;
-      this.variableItemList = cloner.Clone<ICheckedItemList<StringValue>>(variableItemList);
+    public PreprocessingChartContent(PreprocessingChartContent original, Cloner cloner)
+      : base(original, cloner) {
+      variableItemList = cloner.Clone(original.variableItemList);
     }
     public override IDeepCloneable Clone(Cloner cloner) {
       return new PreprocessingChartContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected PreprocessingChartContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
 
     public DataRow CreateDataRow(string variableName, DataRowVisualProperties.DataRowChartType chartType) {
@@ -75,7 +82,11 @@
 
     public static DataRow CreateDataRow(IFilteredPreprocessingData preprocessingData, string variableName, DataRowVisualProperties.DataRowChartType chartType) {
-      IList<double> values = preprocessingData.GetValues<double>(preprocessingData.GetColumnIndex(variableName));
-      DataRow row = new DataRow(variableName, "", values);
-      row.VisualProperties.ChartType = chartType;
+      var values = preprocessingData.GetValues<double>(preprocessingData.GetColumnIndex(variableName));
+      var row = new DataRow(variableName, "", values) {
+        VisualProperties = {
+          ChartType = chartType,
+          StartIndexZero = true
+        }
+      };
       return row;
     }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingContent.cs	(revision 15535)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingContent.cs	(revision 15535)
@@ -0,0 +1,49 @@
+﻿#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 HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("PreprocessingContent", "")]
+  [StorableClass]
+  public abstract class PreprocessingContent : Item {
+
+    public IFilteredPreprocessingData PreprocessingData { get; private set; }
+
+    #region Constructor, Cloning & Persistence
+    protected PreprocessingContent(IFilteredPreprocessingData preprocessingData) {
+      PreprocessingData = preprocessingData;
+    }
+
+    protected PreprocessingContent(PreprocessingContent original, Cloner cloner)
+      : base(original, cloner) {
+      PreprocessingData = cloner.Clone(original.PreprocessingData);
+    }
+
+    [StorableConstructor]
+    protected PreprocessingContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+  }
+}
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 15535)
@@ -25,18 +25,29 @@
 using HeuristicLab.Analysis;
 using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Visualization.ChartControlsExtensions;
 
 namespace HeuristicLab.DataPreprocessing {
-
+  [Item("ScatterPlotContent", "")]
+  [StorableClass]
   public abstract class ScatterPlotContent : PreprocessingChartContent {
+    [Storable]
     public string GroupingVariable { get; set; }
 
+    #region Constructor, Cloning & Persistence
     protected ScatterPlotContent(IFilteredPreprocessingData preprocessingData)
       : base(preprocessingData) {
     }
 
-    protected ScatterPlotContent(ScatterPlotContent content, Cloner cloner)
-      : base(content, cloner) {
+    protected ScatterPlotContent(ScatterPlotContent original, Cloner cloner)
+      : base(original, cloner) {
+      GroupingVariable = original.GroupingVariable;
     }
+
+    [StorableConstructor]
+    protected ScatterPlotContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
 
     public static ScatterPlot CreateScatterPlot(IFilteredPreprocessingData preprocessingData, string variableNameX, string variableNameY, string variableNameGroup = "-", LegendOrder legendOrder = LegendOrder.Alphabetically) {
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/SingleScatterPlotContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/SingleScatterPlotContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/SingleScatterPlotContent.cs	(revision 15535)
@@ -23,8 +23,9 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
-
   [Item("Scatter Plot", "Represents a scatter plot.")]
+  [StorableClass]
   public class SingleScatterPlotContent : ScatterPlotContent {
     public static new Image StaticItemImage {
@@ -32,21 +33,27 @@
     }
 
+    [Storable]
     public string SelectedXVariable { get; set; }
+    [Storable]
     public string SelectedYVariable { get; set; }
 
+    #region Constructor, Cloning & Persistence
     public SingleScatterPlotContent(IFilteredPreprocessingData preprocessingData)
       : base(preprocessingData) {
     }
 
-    public SingleScatterPlotContent(SingleScatterPlotContent content, Cloner cloner)
-      : base(content, cloner) {
-      this.SelectedXVariable = content.SelectedXVariable;
-      this.SelectedYVariable = content.SelectedYVariable;
-      this.GroupingVariable = content.GroupingVariable;
+    public SingleScatterPlotContent(SingleScatterPlotContent original, Cloner cloner)
+      : base(original, cloner) {
+      SelectedXVariable = original.SelectedXVariable;
+      SelectedYVariable = original.SelectedYVariable;
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new SingleScatterPlotContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected SingleScatterPlotContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 15535)
@@ -23,31 +23,34 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Statistics", "Represents the statistics grid.")]
-  public class StatisticsContent : Item, IViewShortcut {
+  [StorableClass]
+  public class StatisticsContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Object; }
     }
 
-    public ITransactionalPreprocessingData PreprocessingData { get; private set; }
-    public StatisticsLogic StatisticsLogic { get; private set; }
-
-    public StatisticsContent(ITransactionalPreprocessingData preProcessingData, StatisticsLogic statisticsLogic) {
-      PreprocessingData = preProcessingData;
-      StatisticsLogic = statisticsLogic;
+    #region Constructor, Cloning & Persistence
+    public StatisticsContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
     }
 
-    public StatisticsContent(StatisticsContent content, Cloner cloner)
-      : base(content, cloner) {
+    public StatisticsContent(StatisticsContent original, Cloner cloner)
+      : base(original, cloner) {
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new StatisticsContent(this, cloner);
     }
 
+    [StorableConstructor]
+    protected StatisticsContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+
     public event DataPreprocessingChangedEventHandler Changed {
-      add { StatisticsLogic.Changed += value; }
-      remove { StatisticsLogic.Changed -= value; }
+      add { PreprocessingData.Changed += value; }
+      remove { PreprocessingData.Changed -= value; }
     }
   }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs	(revision 15535)
@@ -23,33 +23,36 @@
 using HeuristicLab.Common;
 using HeuristicLab.Core;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
 namespace HeuristicLab.DataPreprocessing {
   [Item("Transformation", "Represents the transformation grid.")]
-  public class TransformationContent : Item, IViewShortcut {
+  [StorableClass]
+  public class TransformationContent : PreprocessingContent, IViewShortcut {
     public static new Image StaticItemImage {
       get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
     }
 
-    public IPreprocessingData Data { get; private set; }
-    public FilterLogic FilterLogic { get; private set; }
-
+    [Storable]
     public ICheckedItemList<ITransformation> CheckedTransformationList { get; private set; }
 
-    public TransformationContent(IPreprocessingData data, FilterLogic filterLogic) {
-      Data = data;
+    #region Constructor, Cloning & Persistence
+    public TransformationContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
       CheckedTransformationList = new CheckedItemList<ITransformation>();
-      FilterLogic = filterLogic;
     }
 
     public TransformationContent(TransformationContent original, Cloner cloner)
       : base(original, cloner) {
-      Data = original.Data;
-      CheckedTransformationList = new CheckedItemList<ITransformation>(original.CheckedTransformationList);
+      CheckedTransformationList = cloner.Clone(original.CheckedTransformationList);
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new TransformationContent(this, cloner);
     }
+
+    [StorableConstructor]
+    protected TransformationContent(bool deserializing)
+      : base(deserializing) { }
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 15535)
@@ -22,14 +22,176 @@
 using System;
 using System.Collections.Generic;
+using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
 namespace HeuristicLab.DataPreprocessing {
-  public class FilteredPreprocessingData : NamedItem, IFilteredPreprocessingData {
-    private readonly ITransactionalPreprocessingData originalData;
-    private ITransactionalPreprocessingData filteredData;
-
+  [Item("FilteredPreprocessingData", "Represents filtered data used for preprocessing.")]
+  [StorableClass]
+  public sealed class FilteredPreprocessingData : NamedItem, IFilteredPreprocessingData {
+
+    [Storable]
+    private readonly IPreprocessingData originalData;
+    [Storable]
+    private IPreprocessingData filteredData;
+
+    public IPreprocessingData ActiveData {
+      get { return IsFiltered ? filteredData : originalData; }
+    }
+
+    #region Constructor, Cloning & Persistence
+    public FilteredPreprocessingData(IPreprocessingData preprocessingData)
+      : base() {
+      originalData = preprocessingData;
+      filteredData = null;
+    }
+
+    private FilteredPreprocessingData(FilteredPreprocessingData original, Cloner cloner)
+      : base(original, cloner) {
+      originalData = original.originalData;
+      filteredData = original.filteredData;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FilteredPreprocessingData(this, cloner);
+    }
+
+    [StorableConstructor]
+    private FilteredPreprocessingData(bool deserializing)
+      : base(deserializing) { }
+    #endregion
+
+    #region Cells
+    public bool IsCellEmpty(int columnIndex, int rowIndex) {
+      return ActiveData.IsCellEmpty(columnIndex, rowIndex);
+    }
+
+    public T GetCell<T>(int columnIndex, int rowIndex) {
+      return ActiveData.GetCell<T>(columnIndex, rowIndex);
+    }
+
+    public void SetCell<T>(int columnIndex, int rowIndex, T value) {
+      if (IsFiltered)
+        throw new InvalidOperationException("SetValues not possible while data is filtered");
+      originalData.SetCell<T>(columnIndex, rowIndex, value);
+    }
+
+    public string GetCellAsString(int columnIndex, int rowIndex) {
+      return ActiveData.GetCellAsString(columnIndex, rowIndex);
+    }
+
+    public IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
+      return ActiveData.GetValues<T>(columnIndex, considerSelection);
+    }
+
+    public void SetValues<T>(int columnIndex, IList<T> values) {
+      if (IsFiltered)
+        throw new InvalidOperationException("SetValues not possible while data is filtered");
+
+      originalData.SetValues<T>(columnIndex, values);
+    }
+
+    public bool SetValue(string value, int columnIndex, int rowIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("SetValue not possible while data is filtered");
+      return originalData.SetValue(value, columnIndex, rowIndex);
+    }
+
+    public int Columns {
+      get { return ActiveData.Columns; }
+    }
+
+    public int Rows {
+      get { return ActiveData.Rows; }
+    }
+    #endregion
+
+    #region Rows
+    public void InsertRow(int rowIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("InsertRow not possible while data is filtered");
+
+      originalData.InsertRow(rowIndex);
+    }
+
+    public void DeleteRow(int rowIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("DeleteRow not possible while data is filtered");
+
+      originalData.DeleteRow(rowIndex);
+    }
+
+    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
+      if (IsFiltered)
+        throw new InvalidOperationException("DeleteRowsWithIndices not possible while data is filtered");
+
+      originalData.DeleteRowsWithIndices(rows);
+    }
+
+    public void InsertColumn<T>(string variableName, int columnIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("InsertColumn not possible while data is filtered");
+
+      originalData.InsertColumn<T>(variableName, columnIndex);
+    }
+
+    public void DeleteColumn(int columnIndex) {
+      if (IsFiltered)
+        throw new InvalidOperationException("DeleteColumn not possible while data is filtered");
+      originalData.DeleteColumn(columnIndex);
+    }
+
+    public void RenameColumn(int columnIndex, string name) {
+      if (IsFiltered)
+        throw new InvalidOperationException("RenameColumn not possible while data is filtered");
+      originalData.RenameColumn(columnIndex, name);
+    }
+
+    public void RenameColumns(IList<string> names) {
+      if (IsFiltered)
+        throw new InvalidOperationException("RenameColumns not possible while data is filtered");
+      originalData.RenameColumns(names);
+    }
+
+    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
+      return originalData.AreAllStringColumns(columnIndices);
+    }
+    #endregion
+
+    #region Variables
+    public IEnumerable<string> VariableNames {
+      get { return ActiveData.VariableNames; }
+    }
+    public IEnumerable<string> GetDoubleVariableNames() {
+      return originalData.GetDoubleVariableNames();
+    }
+    public string GetVariableName(int columnIndex) {
+      return ActiveData.GetVariableName(columnIndex);
+    }
+
+    public int GetColumnIndex(string variableName) {
+      return ActiveData.GetColumnIndex(variableName);
+    }
+
+    public bool VariableHasType<T>(int columnIndex) {
+      return originalData.VariableHasType<T>(columnIndex);
+    }
+
+    public Type GetVariableType(int columnIndex) {
+      return ActiveData.GetVariableType(columnIndex);
+    }
+
+    public IList<string> InputVariables {
+      get { return ActiveData.InputVariables; }
+    }
+
+    public string TargetVariable {
+      get { return ActiveData.TargetVariable; }
+    } // optional
+    #endregion
+
+    #region Partitions
     public IntRange TrainingPartition {
       get { return originalData.TrainingPartition; }
@@ -39,16 +201,31 @@
       get { return originalData.TestPartition; }
     }
-
+    #endregion
+
+    #region Transformations
     public IList<ITransformation> Transformations {
       get { return originalData.Transformations; }
     }
-
-    public IEnumerable<string> VariableNames {
-      get { return ActiveData.VariableNames; }
-    }
-
-    public IList<string> InputVariables { get { return ActiveData.InputVariables; } }
-    public string TargetVariable { get { return ActiveData.TargetVariable; } } // optional
-
+    #endregion
+
+    #region Validation
+    public bool Validate(string value, out string errorMessage, int columnIndex) {
+      return originalData.Validate(value, out errorMessage, columnIndex);
+    }
+    #endregion
+
+    #region Import & Export
+    public void Import(IDataAnalysisProblemData problemData) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Import not possible while data is filtered");
+      originalData.Import(problemData);
+    }
+
+    public Dataset ExportToDataset() {
+      return originalData.ExportToDataset();
+    }
+    #endregion
+
+    #region Selection
     public IDictionary<int, IList<int>> Selection {
       get { return originalData.Selection; }
@@ -56,14 +233,18 @@
     }
 
-    public int Columns {
-      get { return ActiveData.Columns; }
-    }
-
-    public int Rows {
-      get { return ActiveData.Rows; }
-    }
-
-    public ITransactionalPreprocessingData ActiveData {
-      get { return IsFiltered ? filteredData : originalData; }
+    public void ClearSelection() {
+      originalData.ClearSelection();
+    }
+
+    public event EventHandler SelectionChanged {
+      add { originalData.SelectionChanged += value; }
+      remove { originalData.SelectionChanged -= value; }
+    }
+    #endregion
+
+    #region Transactions
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { originalData.Changed += value; }
+      remove { originalData.Changed -= value; }
     }
 
@@ -72,110 +253,88 @@
     }
 
-    public bool IsFiltered {
-      get { return filteredData != null; }
-    }
-
-
-    public FilteredPreprocessingData(ITransactionalPreprocessingData preporcessingData)
-      : base() {
-      originalData = preporcessingData;
-      filteredData = null;
-    }
-
-    protected FilteredPreprocessingData(FilteredPreprocessingData original, Cloner cloner)
-      : base(original, cloner) {
-      originalData = original.originalData;
-      filteredData = original.filteredData;
-    }
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new FilteredPreprocessingData(this, cloner);
-    }
-
-    public T GetCell<T>(int columnIndex, int rowIndex) {
-      return ActiveData.GetCell<T>(columnIndex, rowIndex);
-    }
-
-    public void SetCell<T>(int columnIndex, int rowIndex, T value) {
-      if (IsFiltered)
-        throw new InvalidOperationException("SetValues not possible while data is filtered");
-      originalData.SetCell<T>(columnIndex, rowIndex, value);
-    }
-
-    public string GetCellAsString(int columnIndex, int rowIndex) {
-      return ActiveData.GetCellAsString(columnIndex, rowIndex);
-    }
-
-    public IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
-      return ActiveData.GetValues<T>(columnIndex, considerSelection);
-    }
-
-    public void SetValues<T>(int columnIndex, IList<T> values) {
-      if (IsFiltered)
-        throw new InvalidOperationException("SetValues not possible while data is filtered");
-
-      originalData.SetValues<T>(columnIndex, values);
-    }
-
-    public void InsertRow(int rowIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("InsertRow not possible while data is filtered");
-
-      originalData.InsertRow(rowIndex);
-    }
-
-    public void DeleteRow(int rowIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("DeleteRow not possible while data is filtered");
-
-      originalData.DeleteRow(rowIndex);
-    }
-
-    public void InsertColumn<T>(string variableName, int columnIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("InsertColumn not possible while data is filtered");
-
-      originalData.InsertColumn<T>(variableName, columnIndex);
-    }
-
-    public void DeleteColumn(int columnIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("DeleteColumn not possible while data is filtered");
-      originalData.DeleteColumn(columnIndex);
-    }
-
-    public void RenameColumn(int columnIndex, string name) {
-      if (IsFiltered)
-        throw new InvalidOperationException("RenameColumn not possible while data is filtered");
-      originalData.RenameColumn(columnIndex, name);
-    }
-
-    public void RenameColumns(IList<string> names) {
-      if (IsFiltered)
-        throw new InvalidOperationException("RenameColumns not possible while data is filtered");
-      originalData.RenameColumns(names);
-    }
-
-    public string GetVariableName(int columnIndex) {
-      return ActiveData.GetVariableName(columnIndex);
-    }
-
-    public int GetColumnIndex(string variableName) {
-      return ActiveData.GetColumnIndex(variableName);
-    }
-
-    public bool VariableHasType<T>(int columnIndex) {
-      return originalData.VariableHasType<T>(columnIndex);
-    }
-
-    public Dataset ExportToDataset() {
-      return originalData.ExportToDataset();
-    }
-
-    public void SetFilter(bool[] rowFilters) {
-      filteredData = (ITransactionalPreprocessingData)originalData.Clone();
+    public void Undo() {
+      if (IsFiltered)
+        throw new InvalidOperationException("Undo not possible while data is filtered");
+
+      originalData.Undo();
+    }
+
+    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Transaction not possible while data is filtered");
+      originalData.InTransaction(action, type);
+    }
+
+    public void BeginTransaction(DataPreprocessingChangedEventType type) {
+      if (IsFiltered)
+        throw new InvalidOperationException("Transaction not possible while data is filtered");
+      originalData.BeginTransaction(type);
+    }
+
+    public void EndTransaction() {
+      originalData.EndTransaction();
+    }
+    #endregion
+
+    #region Statistics
+    public T GetMin<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      return ActiveData.GetMin<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetMax<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      return ActiveData.GetMax<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetMean<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      return ActiveData.GetMean<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetMedian<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T> {
+      return ActiveData.GetMean<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetMode<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IEquatable<T> {
+      return ActiveData.GetMode<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetStandardDeviation<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      return ActiveData.GetStandardDeviation<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetVariance<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      return ActiveData.GetVariance<T>(columnIndex, considerSelection, emptyValue);
+    }
+    public T GetQuantile<T>(double alpha, int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T> {
+      return ActiveData.GetQuantile<T>(alpha, columnIndex, considerSelection, emptyValue);
+    }
+    public int GetDistinctValues<T>(int columnIndex, bool considerSelection = false) {
+      return ActiveData.GetDistinctValues<T>(columnIndex, considerSelection);
+    }
+
+    public int GetMissingValueCount() {
+      return ActiveData.GetMissingValueCount();
+    }
+    public int GetMissingValueCount(int columnIndex) {
+      return ActiveData.GetMissingValueCount(columnIndex);
+    }
+    public int GetRowMissingValueCount(int rowIndex) {
+      return ActiveData.GetRowMissingValueCount(rowIndex);
+    }
+    #endregion
+
+    #region Filters
+    public void SetFilter(bool[] remainingRows) {
+      filteredData = (IPreprocessingData)originalData.Clone();
       filteredData.InTransaction(() => {
-        for (int row = (rowFilters.Length - 1); row >= 0; --row) {
-          if (rowFilters[row]) {
-            filteredData.DeleteRow(row);
+        var remainingIndices = Enumerable.Range(0, remainingRows.Length).Where(x => remainingRows[x]);
+
+        foreach (var v in filteredData.VariableNames) {
+          var ci = filteredData.GetColumnIndex(v);
+          if (filteredData.VariableHasType<double>(ci)) {
+            var values = filteredData.GetValues<double>(ci);
+            var filteredValues = remainingIndices.Select(x => values[x]).ToList();
+            filteredData.SetValues(ci, filteredValues);
+          } else if (filteredData.VariableHasType<DateTime>(ci)) {
+            var values = filteredData.GetValues<DateTime>(ci);
+            var filteredValues = remainingIndices.Select(x => values[x]).ToList();
+            filteredData.SetValues(ci, filteredValues);
+          } else if (filteredData.VariableHasType<string>(ci)) {
+            var values = filteredData.GetValues<string>(ci);
+            var filteredValues = remainingIndices.Select(x => values[x]).ToList();
+            filteredData.SetValues(ci, filteredValues);
           }
         }
@@ -206,4 +365,10 @@
     }
 
+    public bool IsFiltered {
+      get { return filteredData != null; }
+    }
+
+    public event EventHandler FilterChanged;
+
     private void OnFilterChanged() {
       if (FilterChanged != null) {
@@ -211,69 +376,4 @@
       }
     }
-
-    public event DataPreprocessingChangedEventHandler Changed {
-      add { originalData.Changed += value; }
-      remove { originalData.Changed -= value; }
-    }
-
-    public bool SetValue(string value, int columnIndex, int rowIndex) {
-      if (IsFiltered)
-        throw new InvalidOperationException("SetValue not possible while data is filtered");
-      return originalData.SetValue(value, columnIndex, rowIndex);
-    }
-
-    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
-      return originalData.AreAllStringColumns(columnIndices);
-    }
-
-    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
-      if (IsFiltered)
-        throw new InvalidOperationException("DeleteRowsWithIndices not possible while data is filtered");
-
-      originalData.DeleteRowsWithIndices(rows);
-    }
-
-    public void Undo() {
-      if (IsFiltered)
-        throw new InvalidOperationException("Undo not possible while data is filtered");
-
-      originalData.Undo();
-    }
-
-    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
-      if (IsFiltered)
-        throw new InvalidOperationException("Transaction not possible while data is filtered");
-      originalData.InTransaction(action, type);
-    }
-
-    public void BeginTransaction(DataPreprocessingChangedEventType type) {
-      if (IsFiltered)
-        throw new InvalidOperationException("Transaction not possible while data is filtered");
-      originalData.BeginTransaction(type);
-    }
-
-    public void EndTransaction() {
-      originalData.EndTransaction();
-    }
-
-    public IEnumerable<string> GetDoubleVariableNames() {
-      return originalData.GetDoubleVariableNames();
-    }
-
-    public void ClearSelection() {
-      originalData.ClearSelection();
-    }
-
-    public event EventHandler SelectionChanged {
-      add { originalData.SelectionChanged += value; }
-      remove { originalData.SelectionChanged -= value; }
-    }
-
-    #region IPreprocessingData Members
-    public bool Validate(string value, out string errorMessage, int columnIndex) {
-      return originalData.Validate(value, out errorMessage, columnIndex);
-    }
-
-    public event EventHandler FilterChanged;
     #endregion
   }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 15535)
@@ -23,6 +23,7 @@
 
 namespace HeuristicLab.DataPreprocessing {
-  public interface IFilteredPreprocessingData : ITransactionalPreprocessingData {
-    void SetFilter(bool[] rowFilters);
+  public interface IFilteredPreprocessingData : IPreprocessingData {
+    #region Filters
+    void SetFilter(bool[] remainingRows);
     void PersistFilter();
     void ResetFilter();
@@ -30,4 +31,5 @@
 
     event EventHandler FilterChanged;
+    #endregion
   }
 }
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 15535)
@@ -28,4 +28,6 @@
 namespace HeuristicLab.DataPreprocessing {
   public interface IPreprocessingData : INamedItem {
+    #region Cells
+    bool IsCellEmpty(int columnIndex, int rowIndex);
     T GetCell<T>(int columnIndex, int rowIndex);
 
@@ -39,4 +41,9 @@
     bool SetValue(string value, int columnIndex, int rowIndex);
 
+    int Columns { get; }
+    int Rows { get; }
+    #endregion
+
+    #region Rows
     void InsertRow(int rowIndex);
     void DeleteRow(int rowIndex);
@@ -50,11 +57,7 @@
 
     bool AreAllStringColumns(IEnumerable<int> columnIndices);
-    bool Validate(string value, out string errorMessage, int columnIndex);
+    #endregion
 
-    IntRange TrainingPartition { get; }
-    IntRange TestPartition { get; }
-
-    IList<ITransformation> Transformations { get; }
-
+    #region Variables
     IEnumerable<string> VariableNames { get; }
     IEnumerable<string> GetDoubleVariableNames();
@@ -63,17 +66,60 @@
 
     bool VariableHasType<T>(int columnIndex);
+    Type GetVariableType(int columnIndex);
 
     IList<string> InputVariables { get; }
     string TargetVariable { get; } // optional
+    #endregion
 
-    int Columns { get; }
-    int Rows { get; }
+    #region Partitions
+    IntRange TrainingPartition { get; }
+    IntRange TestPartition { get; }
+    #endregion
 
+    #region Transformations
+    IList<ITransformation> Transformations { get; }
+    #endregion
+
+    #region Validation
+    bool Validate(string value, out string errorMessage, int columnIndex);
+    #endregion
+
+    #region Import & Export
+    void Import(IDataAnalysisProblemData problemData);
     Dataset ExportToDataset();
+    #endregion
 
+    #region Selection
     IDictionary<int, IList<int>> Selection { get; set; }
     void ClearSelection();
 
     event EventHandler SelectionChanged;
+    #endregion
+
+    #region Transactions
+    event DataPreprocessingChangedEventHandler Changed;
+
+    bool IsUndoAvailable { get; }
+    void Undo();
+    void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any);
+    void BeginTransaction(DataPreprocessingChangedEventType type);
+    void EndTransaction();
+    #endregion
+
+    #region Statistics
+    T GetMin<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T));
+    T GetMax<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T));
+    T GetMean<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T));
+    T GetMedian<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T>;
+    T GetMode<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IEquatable<T>;
+    T GetStandardDeviation<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T));
+    T GetVariance<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T));
+    T GetQuantile<T>(double alpha, int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T>;
+    int GetDistinctValues<T>(int columnIndex, bool considerSelection = false);
+
+    int GetMissingValueCount();
+    int GetMissingValueCount(int columnIndex);
+    int GetRowMissingValueCount(int rowIndex);
+    #endregion
   }
 }
Index: able/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs	(revision 15534)
+++ 	(revision )
@@ -1,34 +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;
-
-namespace HeuristicLab.DataPreprocessing {
-  public interface ITransactionalPreprocessingData : IPreprocessingData {
-    event DataPreprocessingChangedEventHandler Changed;
-
-    bool IsUndoAvailable { get; }
-    void Undo();
-    void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any);
-    void BeginTransaction(DataPreprocessingChangedEventType type);
-    void EndTransaction();
-  }
-}
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 15535)
@@ -23,8 +23,10 @@
 using System.Collections;
 using System.Collections.Generic;
+using System.Globalization;
 using System.Linq;
 using HeuristicLab.Common;
 using HeuristicLab.Core;
 using HeuristicLab.Data;
+using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
 using HeuristicLab.Problems.DataAnalysis;
 
@@ -32,45 +34,23 @@
 
   [Item("PreprocessingData", "Represents data used for preprocessing.")]
-  public abstract class PreprocessingData : NamedItem, IPreprocessingData {
-    public IntRange TrainingPartition { get; set; }
-    public IntRange TestPartition { get; set; }
-
-    public IList<ITransformation> Transformations { get; protected set; }
-
+  [StorableClass]
+  public class PreprocessingData : NamedItem, IPreprocessingData {
+
+    [Storable]
     protected IList<IList> variableValues;
+    [Storable]
     protected IList<string> variableNames;
 
-    public IEnumerable<string> VariableNames {
-      get { return variableNames; }
-    }
-
-    public IEnumerable<string> GetDoubleVariableNames() {
-      var doubleVariableNames = new List<string>();
-      for (int i = 0; i < Columns; ++i) {
-        if (VariableHasType<double>(i)) {
-          doubleVariableNames.Add(variableNames[i]);
-        }
-      }
-      return doubleVariableNames;
-    }
-
-    public IList<string> InputVariables { get; private set; }
-    public string TargetVariable { get; private set; } // optional
-
-    public int Columns {
-      get { return variableNames.Count; }
-    }
-
-    public int Rows {
-      get { return variableValues.Count > 0 ? variableValues[0].Count : 0; }
-    }
-
-    protected IDictionary<int, IList<int>> selection;
-    public IDictionary<int, IList<int>> Selection {
-      get { return selection; }
-      set {
-        selection = value;
-        OnSelectionChanged();
-      }
+    #region Constructor, Cloning & Persistence
+    public PreprocessingData(IDataAnalysisProblemData problemData)
+      : base() {
+      Name = "Preprocessing Data";
+
+      Transformations = new List<ITransformation>();
+      selection = new Dictionary<int, IList<int>>();
+
+      Import(problemData);
+
+      RegisterEventHandler();
     }
 
@@ -88,17 +68,327 @@
       RegisterEventHandler();
     }
-
-    protected PreprocessingData(IDataAnalysisProblemData problemData)
-      : base() {
-      Name = "Preprocessing Data";
-
-      Transformations = new List<ITransformation>();
-      selection = new Dictionary<int, IList<int>>();
-
-      Import(problemData);
-
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PreprocessingData(this, cloner);
+    }
+
+    [StorableConstructor]
+    protected PreprocessingData(bool deserializing)
+      : base(deserializing) { }
+    [StorableHook(HookType.AfterDeserialization)]
+    private void AfterDeserialization() {
       RegisterEventHandler();
     }
 
+    private void RegisterEventHandler() {
+      Changed += (s, e) => {
+        switch (e.Type) {
+          case DataPreprocessingChangedEventType.DeleteRow:
+          case DataPreprocessingChangedEventType.Any:
+          case DataPreprocessingChangedEventType.Transformation:
+            int maxRowIndex = Math.Max(0, Rows);
+            TrainingPartition.Start = Math.Min(TrainingPartition.Start, maxRowIndex);
+            TrainingPartition.End = Math.Min(TrainingPartition.End, maxRowIndex);
+            TestPartition.Start = Math.Min(TestPartition.Start, maxRowIndex);
+            TestPartition.End = Math.Min(TestPartition.End, maxRowIndex);
+            break;
+        }
+      };
+    }
+    #endregion
+
+    #region Cells
+    public bool IsCellEmpty(int columnIndex, int rowIndex) {
+      var value = variableValues[columnIndex][rowIndex];
+      return IsMissingValue(value);
+    }
+
+    public T GetCell<T>(int columnIndex, int rowIndex) {
+      return (T)variableValues[columnIndex][rowIndex];
+    }
+
+    public void SetCell<T>(int columnIndex, int rowIndex, T value) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
+
+      for (int i = Rows; i <= rowIndex; i++)
+        InsertRow(i);
+      for (int i = Columns; i <= columnIndex; i++)
+        InsertColumn<T>(i.ToString(), i);
+
+      variableValues[columnIndex][rowIndex] = value;
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
+    }
+
+    public string GetCellAsString(int columnIndex, int rowIndex) {
+      return variableValues[columnIndex][rowIndex].ToString();
+    }
+
+    public IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
+      if (considerSelection) {
+        var list = new List<T>();
+        foreach (var rowIdx in selection[columnIndex]) {
+          list.Add((T)variableValues[columnIndex][rowIdx]);
+        }
+        return list;
+      } else {
+        return (IList<T>)variableValues[columnIndex];
+      }
+    }
+
+    public void SetValues<T>(int columnIndex, IList<T> values) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+      if (VariableHasType<T>(columnIndex)) {
+        variableValues[columnIndex] = (IList)values;
+      } else {
+        throw new ArgumentException("The datatype of column " + columnIndex + " must be of type " + variableValues[columnIndex].GetType().Name + " but was " + typeof(T).Name);
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+    }
+
+    public bool SetValue(string value, int columnIndex, int rowIndex) {
+      bool valid = false;
+      if (VariableHasType<double>(columnIndex)) {
+        double val;
+        if (string.IsNullOrWhiteSpace(value)) {
+          val = double.NaN;
+          valid = true;
+        } else {
+          valid = double.TryParse(value, out val);
+        }
+        if (valid)
+          SetCell(columnIndex, rowIndex, val);
+      } else if (VariableHasType<string>(columnIndex)) {
+        valid = value != null;
+        if (valid)
+          SetCell(columnIndex, rowIndex, value);
+      } else if (VariableHasType<DateTime>(columnIndex)) {
+        DateTime date;
+        valid = DateTime.TryParse(value, out date);
+        if (valid)
+          SetCell(columnIndex, rowIndex, date);
+      } else {
+        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
+      }
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+
+      return valid;
+    }
+
+    public int Columns {
+      get { return variableNames.Count; }
+    }
+
+    public int Rows {
+      get { return variableValues.Count > 0 ? variableValues[0].Count : 0; }
+    }
+
+    public static bool IsMissingValue(object value) {
+      if (value is double) return double.IsNaN((double)value);
+      if (value is string) return string.IsNullOrEmpty((string)value);
+      if (value is DateTime) return ((DateTime)value).Equals(DateTime.MinValue);
+      throw new ArgumentException();
+    }
+    #endregion
+
+    #region Rows
+    public void InsertRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
+      foreach (IList column in variableValues) {
+        Type type = column.GetType().GetGenericArguments()[0];
+        column.Insert(rowIndex, type.IsValueType ? Activator.CreateInstance(type) : null);
+      }
+      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+        TrainingPartition.End++;
+        if (TrainingPartition.End <= TestPartition.Start) {
+          TestPartition.Start++;
+          TestPartition.End++;
+        }
+      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+        TestPartition.End++;
+        if (TestPartition.End <= TrainingPartition.Start) {
+          TestPartition.Start++;
+          TestPartition.End++;
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+    }
+    public void DeleteRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+      foreach (IList column in variableValues) {
+        column.RemoveAt(rowIndex);
+      }
+      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+        TrainingPartition.End--;
+        if (TrainingPartition.End <= TestPartition.Start) {
+          TestPartition.Start--;
+          TestPartition.End--;
+        }
+      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+        TestPartition.End--;
+        if (TestPartition.End <= TrainingPartition.Start) {
+          TestPartition.Start--;
+          TestPartition.End--;
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
+    }
+    public void DeleteRowsWithIndices(IEnumerable<int> rows) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, -1);
+      foreach (int rowIndex in rows.OrderByDescending(x => x)) {
+        foreach (IList column in variableValues) {
+          column.RemoveAt(rowIndex);
+        }
+        if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
+          TrainingPartition.End--;
+          if (TrainingPartition.End <= TestPartition.Start) {
+            TestPartition.Start--;
+            TestPartition.End--;
+          }
+        } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
+          TestPartition.End--;
+          if (TestPartition.End <= TrainingPartition.Start) {
+            TestPartition.Start--;
+            TestPartition.End--;
+          }
+        }
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, -1);
+    }
+
+    public void InsertColumn<T>(string variableName, int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
+      variableValues.Insert(columnIndex, new List<T>(Enumerable.Repeat(default(T), Rows)));
+      variableNames.Insert(columnIndex, variableName);
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
+    }
+
+    public void DeleteColumn(int columnIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
+      variableValues.RemoveAt(columnIndex);
+      variableNames.RemoveAt(columnIndex);
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
+    }
+
+    public void RenameColumn(int columnIndex, string name) {
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
+      if (columnIndex < 0 || columnIndex > variableNames.Count)
+        throw new ArgumentOutOfRangeException("columnIndex");
+      variableNames[columnIndex] = name;
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+    }
+
+    public void RenameColumns(IList<string> names) {
+      if (names == null) throw new ArgumentNullException("names");
+      if (names.Count != variableNames.Count) throw new ArgumentException("number of names must match the number of columns.", "names");
+
+      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+      for (int i = 0; i < names.Count; i++)
+        variableNames[i] = names[i];
+
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
+    }
+
+    public bool AreAllStringColumns(IEnumerable<int> columnIndices) {
+      return columnIndices.All(x => VariableHasType<string>(x));
+    }
+    #endregion
+
+    #region Variables
+    public IEnumerable<string> VariableNames {
+      get { return variableNames; }
+    }
+
+    public IEnumerable<string> GetDoubleVariableNames() {
+      var doubleVariableNames = new List<string>();
+      for (int i = 0; i < Columns; ++i) {
+        if (VariableHasType<double>(i)) {
+          doubleVariableNames.Add(variableNames[i]);
+        }
+      }
+      return doubleVariableNames;
+    }
+
+    public string GetVariableName(int columnIndex) {
+      return variableNames[columnIndex];
+    }
+
+    public int GetColumnIndex(string variableName) {
+      return variableNames.IndexOf(variableName);
+    }
+
+    public bool VariableHasType<T>(int columnIndex) {
+      return columnIndex >= variableValues.Count || variableValues[columnIndex] is List<T>;
+    }
+
+    public Type GetVariableType(int columnIndex) {
+      var listType = variableValues[columnIndex].GetType();
+      return listType.GenericTypeArguments.Single();
+    }
+
+    public IList<string> InputVariables { get; private set; }
+    public string TargetVariable { get; private set; } // optional
+    #endregion
+
+    #region Partitions
+    [Storable]
+    public IntRange TrainingPartition { get; set; }
+    [Storable]
+    public IntRange TestPartition { get; set; }
+    #endregion
+
+    #region Transformations
+    [Storable]
+    public IList<ITransformation> Transformations { get; protected set; }
+    #endregion
+
+    #region Validation
+    public bool Validate(string value, out string errorMessage, int columnIndex) {
+      if (columnIndex < 0 || columnIndex > VariableNames.Count()) {
+        throw new ArgumentOutOfRangeException("column index is out of range");
+      }
+
+      bool valid = false;
+      errorMessage = string.Empty;
+      if (VariableHasType<double>(columnIndex)) {
+        if (string.IsNullOrWhiteSpace(value)) {
+          valid = true;
+        } else {
+          double val;
+          valid = double.TryParse(value, out val);
+          if (!valid) {
+            errorMessage = "Invalid Value (Valid Value Format: \"" + FormatPatterns.GetDoubleFormatPattern() + "\")";
+          }
+        }
+      } else if (VariableHasType<string>(columnIndex)) {
+        valid = value != null;
+        if (!valid) {
+          errorMessage = "Invalid Value (string must not be null)";
+        }
+      } else if (VariableHasType<DateTime>(columnIndex)) {
+        DateTime date;
+        valid = DateTime.TryParse(value, out date);
+        if (!valid) {
+          errorMessage = "Invalid Value (Valid Value Format: \"" + CultureInfo.CurrentCulture.DateTimeFormat + "\"";
+        }
+      } else {
+        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
+      }
+
+      return valid;
+    }
+    #endregion
+
+    #region Import & Export
     public void Import(IDataAnalysisProblemData problemData) {
       Dataset dataset = (Dataset)problemData.Dataset;
@@ -107,5 +397,5 @@
       TargetVariable = (problemData is IRegressionProblemData) ? ((IRegressionProblemData)problemData).TargetVariable
         : (problemData is IClassificationProblemData) ? ((IClassificationProblemData)problemData).TargetVariable
-        : null;
+          : null;
 
       int columnIndex = 0;
@@ -128,82 +418,51 @@
     }
 
-    private void RegisterEventHandler() {
-      Changed += (s, e) => {
-        switch (e.Type) {
-          case DataPreprocessingChangedEventType.DeleteRow:
-            CheckPartitionRanges();
-            break;
-          case DataPreprocessingChangedEventType.Any:
-            CheckPartitionRanges();
-            break;
-          case DataPreprocessingChangedEventType.Transformation:
-            CheckPartitionRanges();
-            break;
-        }
-      };
-    }
-
-    private void CheckPartitionRanges() {
-      int maxRowIndex = Math.Max(0, Rows);
-      TrainingPartition.Start = Math.Min(TrainingPartition.Start, maxRowIndex);
-      TrainingPartition.End = Math.Min(TrainingPartition.End, maxRowIndex);
-      TestPartition.Start = Math.Min(TestPartition.Start, maxRowIndex);
-      TestPartition.End = Math.Min(TestPartition.End, maxRowIndex);
-    }
-
-    protected IList<IList> CopyVariableValues(IList<IList> original) {
-      var copy = new List<IList>(original);
-      for (int i = 0; i < original.Count; ++i) {
-        copy[i] = (IList)Activator.CreateInstance(original[i].GetType(), original[i]);
-      }
-      return copy;
-    }
-
-
-    #region IPreprocessingData Members
-    public abstract T GetCell<T>(int columnIndex, int rowIndex);
-
-    public abstract void SetCell<T>(int columnIndex, int rowIndex, T value);
-
-    public abstract string GetCellAsString(int columnIndex, int rowIndex);
-
-    public abstract string GetVariableName(int columnIndex);
-
-    public abstract int GetColumnIndex(string variableName);
-
-    public abstract bool VariableHasType<T>(int columnIndex);
-
-    [Obsolete("use the index based variant, is faster")]
-    public abstract IList<T> GetValues<T>(string variableName, bool considerSelection);
-
-    public abstract IList<T> GetValues<T>(int columnIndex, bool considerSelection);
-
-    public abstract void SetValues<T>(int columnIndex, IList<T> values);
-
-    public abstract bool SetValue(string value, int columnIndex, int rowIndex);
-
-    public abstract bool Validate(string value, out string errorMessage, int columnIndex);
-
-    public abstract bool AreAllStringColumns(IEnumerable<int> columnIndices);
-
-    public abstract void DeleteRowsWithIndices(IEnumerable<int> rows);
-
-    public abstract void InsertRow(int rowIndex);
-
-    public abstract void DeleteRow(int rowIndex);
-
-    public abstract void InsertColumn<T>(string variableName, int columnIndex);
-
-    public abstract void DeleteColumn(int columnIndex);
-
-    public abstract void RenameColumn(int columnIndex, string name);
-    public abstract void RenameColumns(IList<string> list);
-
-    public abstract Dataset ExportToDataset();
-
-    public abstract void ClearSelection();
-
-    public abstract event EventHandler SelectionChanged;
-    protected abstract void OnSelectionChanged();
+    public Dataset ExportToDataset() {
+      IList<IList> values = new List<IList>();
+
+      for (int i = 0; i < Columns; ++i) {
+        values.Add(variableValues[i]);
+      }
+
+      var dataset = new Dataset(variableNames, values);
+      return dataset;
+    }
+    #endregion
+
+    #region Selection
+    [Storable]
+    protected IDictionary<int, IList<int>> selection;
+    public IDictionary<int, IList<int>> Selection {
+      get { return selection; }
+      set {
+        selection = value;
+        OnSelectionChanged();
+      }
+    }
+    public void ClearSelection() {
+      Selection = new Dictionary<int, IList<int>>();
+    }
+
+    public event EventHandler SelectionChanged;
+    protected void OnSelectionChanged() {
+      var listeners = SelectionChanged;
+      if (listeners != null) listeners(this, EventArgs.Empty);
+    }
+    #endregion
+
+    #region Transactions
+    // Stapshot/History are nost storable/cloneable on purpose
+    private class Snapshot {
+      public IList<IList> VariableValues { get; set; }
+      public IList<string> VariableNames { get; set; }
+
+      public IntRange TrainingPartition { get; set; }
+      public IntRange TestPartition { get; set; }
+      public IList<ITransformation> Transformations { get; set; }
+      public DataPreprocessingChangedEventType ChangedType { get; set; }
+
+      public int ChangedColumn { get; set; }
+      public int ChangedRow { get; set; }
+    }
 
     public event DataPreprocessingChangedEventHandler Changed;
@@ -212,5 +471,259 @@
       if (listeners != null) listeners(this, new DataPreprocessingChangedEventArgs(type, column, row));
     }
-    #endregion
+
+    private const int MAX_UNDO_DEPTH = 5;
+
+    private readonly IList<Snapshot> undoHistory = new List<Snapshot>();
+    private readonly Stack<DataPreprocessingChangedEventType> eventStack = new Stack<DataPreprocessingChangedEventType>();
+
+    public bool IsInTransaction { get { return eventStack.Count > 0; } }
+
+    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
+      if (IsInTransaction) return;
+
+      var currentSnapshot = new Snapshot {
+        VariableValues = CopyVariableValues(variableValues),
+        VariableNames = new List<string>(variableNames),
+        TrainingPartition = new IntRange(TrainingPartition.Start, TrainingPartition.End),
+        TestPartition = new IntRange(TestPartition.Start, TestPartition.End),
+        Transformations = new List<ITransformation>(Transformations),
+        ChangedType = changedType,
+        ChangedColumn = column,
+        ChangedRow = row
+      };
+
+      if (undoHistory.Count >= MAX_UNDO_DEPTH)
+        undoHistory.RemoveAt(0);
+
+      undoHistory.Add(currentSnapshot);
+    }
+
+    public bool IsUndoAvailable {
+      get { return undoHistory.Count > 0; }
+    }
+
+    public void Undo() {
+      if (IsUndoAvailable) {
+        Snapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
+        variableValues = previousSnapshot.VariableValues;
+        variableNames = previousSnapshot.VariableNames;
+        TrainingPartition = previousSnapshot.TrainingPartition;
+        TestPartition = previousSnapshot.TestPartition;
+        Transformations = previousSnapshot.Transformations;
+        undoHistory.Remove(previousSnapshot);
+        OnChanged(previousSnapshot.ChangedType,
+          previousSnapshot.ChangedColumn,
+          previousSnapshot.ChangedRow);
+      }
+    }
+
+    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
+      BeginTransaction(type);
+      action();
+      EndTransaction();
+    }
+
+    public void BeginTransaction(DataPreprocessingChangedEventType type) {
+      SaveSnapshot(type, -1, -1);
+      eventStack.Push(type);
+    }
+
+    public void EndTransaction() {
+      if (eventStack.Count == 0)
+        throw new InvalidOperationException("There is no open transaction that can be ended.");
+
+      var @event = eventStack.Pop();
+      OnChanged(@event, -1, -1);
+    }
+    #endregion
+
+    #region Statistics
+    public T GetMin<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.Any() ? values.Min() : emptyValue;
+    }
+
+    public T GetMax<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.Any() ? values.Max() : emptyValue;
+    }
+
+    public T GetMean<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      if (typeof(T) == typeof(double)) {
+        var values = GetValuesWithoutMissingValues<double>(columnIndex, considerSelection);
+        return values.Any() ? Convert<T>(values.Average()) : emptyValue;
+      }
+      if (typeof(T) == typeof(string)) {
+        return Convert<T>(string.Empty);
+      }
+      if (typeof(T) == typeof(DateTime)) {
+        var values = GetValuesWithoutMissingValues<DateTime>(columnIndex, considerSelection);
+        return values.Any() ? Convert<T>(AggregateAsDouble(values, Enumerable.Average)) : emptyValue;
+      }
+
+      throw new InvalidOperationException(typeof(T) + " not supported");
+    }
+
+    public T GetMedian<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T> {
+      if (typeof(T) == typeof(double)) {// IEnumerable<double> is faster  
+        var doubleValues = GetValuesWithoutMissingValues<double>(columnIndex, considerSelection);
+        return doubleValues.Any() ? Convert<T>(doubleValues.Median()) : emptyValue;
+      }
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.Any() ? values.Quantile(0.5) : emptyValue;
+    }
+
+    public T GetMode<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IEquatable<T> {
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.Any() ? values.GroupBy(x => x).OrderByDescending(g => g.Count()).Select(g => g.Key).First() : emptyValue;
+    }
+
+    public T GetStandardDeviation<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      if (typeof(T) == typeof(double)) {
+        var values = GetValuesWithoutMissingValues<double>(columnIndex, considerSelection);
+        return values.Any() ? Convert<T>(values.StandardDeviation()) : emptyValue;
+      }
+      // For DateTime, std.dev / variance would have to be TimeSpan
+      //if (typeof(T) == typeof(DateTime)) {
+      //  var values = GetValuesWithoutMissingValues<DateTime>(columnIndex, considerSelection);
+      //  return values.Any() ? Convert<T>(AggregateAsDouble(values, EnumerableStatisticExtensions.StandardDeviation)) : emptyValue;
+      //}
+      return default(T);
+    }
+
+    public T GetVariance<T>(int columnIndex, bool considerSelection = false, T emptyValue = default(T)) {
+      if (typeof(T) == typeof(double)) {
+        var values = GetValuesWithoutMissingValues<double>(columnIndex, considerSelection);
+        return values.Any() ? Convert<T>(values.Variance()) : emptyValue;
+      }
+      // DateTime variance often overflows long, thus the corresponding DateTime is invalid
+      //if (typeof(T) == typeof(DateTime)) {
+      //  var values = GetValuesWithoutMissingValues<DateTime>(columnIndex, considerSelection);
+      //  return values.Any() ? Convert<T>(AggregateAsDouble(values, EnumerableStatisticExtensions.Variance)) : emptyValue;
+      //}
+      return default(T);
+    }
+
+    public T GetQuantile<T>(double alpha, int columnIndex, bool considerSelection = false, T emptyValue = default(T)) where T : IComparable<T> {
+      if (typeof(T) == typeof(double)) {// IEnumerable<double> is faster  
+        var doubleValues = GetValuesWithoutMissingValues<double>(columnIndex, considerSelection);
+        return doubleValues.Any() ? Convert<T>(doubleValues.Quantile(alpha)) : emptyValue;
+      }
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.Any() ? values.Quantile(alpha) : emptyValue;
+    }
+
+    public int GetDistinctValues<T>(int columnIndex, bool considerSelection = false) {
+      var values = GetValuesWithoutMissingValues<T>(columnIndex, considerSelection);
+      return values.GroupBy(x => x).Count();
+    }
+
+    private IEnumerable<T> GetValuesWithoutMissingValues<T>(int columnIndex, bool considerSelection) {
+      return GetValues<T>(columnIndex, considerSelection).Where(x => !IsMissingValue(x));
+    }
+
+    private static DateTime AggregateAsDouble(IEnumerable<DateTime> values, Func<IEnumerable<double>, double> func) {
+      return new DateTime((long)(func(values.Select(x => (double)x.Ticks / TimeSpan.TicksPerSecond)) * TimeSpan.TicksPerSecond));
+    }
+    private static T Convert<T>(object obj) { return (T)obj; }
+
+    public int GetMissingValueCount() {
+      int count = 0;
+      for (int i = 0; i < Columns; ++i) {
+        count += GetMissingValueCount(i);
+      }
+      return count;
+    }
+    public int GetMissingValueCount(int columnIndex) {
+      int sum = 0;
+      for (int i = 0; i < Rows; i++) {
+        if (IsCellEmpty(columnIndex, i))
+          sum++;
+      }
+      return sum;
+    }
+    public int GetRowMissingValueCount(int rowIndex) {
+      int sum = 0;
+      for (int i = 0; i < Columns; i++) {
+        if (IsCellEmpty(i, rowIndex))
+          sum++;
+      }
+      return sum;
+    }
+    #endregion
+
+    #region Helpers
+    private static IList<IList> CopyVariableValues(IList<IList> original) {
+      var copy = new List<IList>(original);
+      for (int i = 0; i < original.Count; ++i) {
+        copy[i] = (IList)Activator.CreateInstance(original[i].GetType(), original[i]);
+      }
+      return copy;
+    }
+    #endregion
+  }
+
+  // Adapted from HeuristicLab.Common.EnumerableStatisticExtensions
+  internal static class EnumerableExtensions {
+    public static T Quantile<T>(this IEnumerable<T> values, double alpha) where T : IComparable<T> {
+      T[] valuesArr = values.ToArray();
+      int n = valuesArr.Length;
+      if (n == 0) throw new InvalidOperationException("Enumeration contains no elements.");
+
+      var pos = n * alpha;
+
+      return Select((int)Math.Ceiling(pos) - 1, valuesArr);
+
+    }
+
+    private static T Select<T>(int k, T[] arr) where T : IComparable<T> {
+      int i, ir, j, l, mid, n = arr.Length;
+      T a;
+      l = 0;
+      ir = n - 1;
+      for (;;) {
+        if (ir <= l + 1) {
+          // Active partition contains 1 or 2 elements.
+          if (ir == l + 1 && arr[ir].CompareTo(arr[l]) < 0) {
+            // Case of 2 elements.
+            Swap(arr, l, ir);
+          }
+          return arr[k];
+        } else {
+          mid = (l + ir) >> 1; // Choose median of left, center, and right elements
+          Swap(arr, mid, l + 1); // as partitioning element a. Also
+
+          if (arr[l].CompareTo(arr[ir]) > 0) {  // rearrange so that arr[l] arr[ir] <= arr[l+1],
+            Swap(arr, l, ir); // . arr[ir] >= arr[l+1]
+          }
+
+          if (arr[l + 1].CompareTo(arr[ir]) > 0) {
+            Swap(arr, l + 1, ir);
+          }
+          if (arr[l].CompareTo(arr[l + 1]) > 0) {
+            Swap(arr, l, l + 1);
+          }
+          i = l + 1; // Initialize pointers for partitioning.
+          j = ir;
+          a = arr[l + 1]; // Partitioning element.
+          for (;;) { // Beginning of innermost loop.
+            do i++; while (arr[i].CompareTo(a) < 0); // Scan up to find element > a.
+            do j--; while (arr[j].CompareTo(a) > 0); // Scan down to find element < a.
+            if (j < i) break; // Pointers crossed. Partitioning complete.
+            Swap(arr, i, j);
+          } // End of innermost loop.
+          arr[l + 1] = arr[j]; // Insert partitioning element.
+          arr[j] = a;
+          if (j >= k) ir = j - 1; // Keep active the partition that contains the
+          if (j <= k) l = i; // kth element.
+        }
+      }
+    }
+
+    private static void Swap<T>(T[] arr, int i, int j) {
+      T temp = arr[i];
+      arr[i] = arr[j];
+      arr[j] = temp;
+    }
   }
 }
Index: able/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs	(revision 15534)
+++ 	(revision )
@@ -1,382 +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;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Linq;
-using HeuristicLab.Common;
-using HeuristicLab.Core;
-using HeuristicLab.Data;
-using HeuristicLab.Problems.DataAnalysis;
-
-namespace HeuristicLab.DataPreprocessing {
-  [Item("PreprocessingData", "Represents data used for preprocessing.")]
-  public class TransactionalPreprocessingData : PreprocessingData, ITransactionalPreprocessingData {
-    private class Snapshot {
-      public IList<IList> VariableValues { get; set; }
-      public IList<string> VariableNames { get; set; }
-
-      public IntRange TrainingPartition { get; set; }
-      public IntRange TestPartition { get; set; }
-      public IList<ITransformation> Transformations { get; set; }
-      public DataPreprocessingChangedEventType ChangedType { get; set; }
-
-      public int ChangedColumn { get; set; }
-      public int ChangedRow { get; set; }
-    }
-
-    private const int MAX_UNDO_DEPTH = 5;
-
-    private readonly IList<Snapshot> undoHistory = new List<Snapshot>();
-    private readonly Stack<DataPreprocessingChangedEventType> eventStack = new Stack<DataPreprocessingChangedEventType>();
-
-    public bool IsInTransaction { get { return eventStack.Count > 0; } }
-
-    public TransactionalPreprocessingData(IDataAnalysisProblemData problemData)
-      : base(problemData) {
-    }
-
-    protected TransactionalPreprocessingData(TransactionalPreprocessingData original, Cloner cloner)
-      : base(original, cloner) {
-    }
-
-    private void SaveSnapshot(DataPreprocessingChangedEventType changedType, int column, int row) {
-      if (IsInTransaction) return;
-
-      var currentSnapshot = new Snapshot {
-        VariableValues = CopyVariableValues(variableValues),
-        VariableNames = new List<string>(variableNames),
-        TrainingPartition = new IntRange(TrainingPartition.Start, TrainingPartition.End),
-        TestPartition = new IntRange(TestPartition.Start, TestPartition.End),
-        Transformations = new List<ITransformation>(Transformations),
-        ChangedType = changedType,
-        ChangedColumn = column,
-        ChangedRow = row
-      };
-
-      if (undoHistory.Count >= MAX_UNDO_DEPTH)
-        undoHistory.RemoveAt(0);
-
-      undoHistory.Add(currentSnapshot);
-    }
-
-    #region NamedItem abstract Member Implementations
-    public override IDeepCloneable Clone(Cloner cloner) {
-      return new TransactionalPreprocessingData(this, cloner);
-    }
-    #endregion
-
-    #region Overridden IPreprocessingData Members
-    public override T GetCell<T>(int columnIndex, int rowIndex) {
-      return (T)variableValues[columnIndex][rowIndex];
-    }
-
-    public override void SetCell<T>(int columnIndex, int rowIndex, T value) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
-
-      for (int i = Rows; i <= rowIndex; i++)
-        InsertRow(i);
-      for (int i = Columns; i <= columnIndex; i++)
-        InsertColumn<T>(i.ToString(), i);
-
-      variableValues[columnIndex][rowIndex] = value;
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeItem, columnIndex, rowIndex);
-    }
-
-    public override string GetCellAsString(int columnIndex, int rowIndex) {
-      return variableValues[columnIndex][rowIndex].ToString();
-    }
-
-    public override string GetVariableName(int columnIndex) {
-      return variableNames[columnIndex];
-    }
-
-    public override int GetColumnIndex(string variableName) {
-      return variableNames.IndexOf(variableName);
-    }
-
-    public override bool VariableHasType<T>(int columnIndex) {
-      return columnIndex >= variableValues.Count || variableValues[columnIndex] is List<T>;
-    }
-
-    [Obsolete("use the index based variant, is faster")]
-    public override IList<T> GetValues<T>(string variableName, bool considerSelection) {
-      return GetValues<T>(GetColumnIndex(variableName), considerSelection);
-    }
-
-    public override IList<T> GetValues<T>(int columnIndex, bool considerSelection) {
-      if (considerSelection) {
-        var list = new List<T>();
-        foreach (var rowIdx in selection[columnIndex]) {
-          list.Add((T)variableValues[columnIndex][rowIdx]);
-        }
-        return list;
-      } else {
-        return (IList<T>)variableValues[columnIndex];
-      }
-    }
-
-    public override void SetValues<T>(int columnIndex, IList<T> values) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-      if (VariableHasType<T>(columnIndex)) {
-        variableValues[columnIndex] = (IList)values;
-      } else {
-        throw new ArgumentException("The datatype of column " + columnIndex + " must be of type " + variableValues[columnIndex].GetType().Name + " but was " + typeof(T).Name);
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-    }
-
-    public override bool SetValue(string value, int columnIndex, int rowIndex) {
-      bool valid = false;
-      if (VariableHasType<double>(columnIndex)) {
-        double val;
-        valid = double.TryParse(value, out val);
-        SetValueIfValid(columnIndex, rowIndex, valid, val);
-      } else if (VariableHasType<string>(columnIndex)) {
-        valid = value != null;
-        SetValueIfValid(columnIndex, rowIndex, valid, value);
-      } else if (VariableHasType<DateTime>(columnIndex)) {
-        DateTime date;
-        valid = DateTime.TryParse(value, out date);
-        SetValueIfValid(columnIndex, rowIndex, valid, date);
-      } else {
-        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
-      }
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-
-      return valid;
-    }
-
-    public override bool Validate(string value, out string errorMessage, int columnIndex) {
-      if (columnIndex < 0 || columnIndex > VariableNames.Count()) {
-        throw new ArgumentOutOfRangeException("column index is out of range");
-      }
-
-      bool valid = false;
-      errorMessage = string.Empty;
-      if (VariableHasType<double>(columnIndex)) {
-        double val;
-        valid = double.TryParse(value, out val);
-        if (!valid) {
-          errorMessage = "Invalid Value (Valid Value Format: \"" + FormatPatterns.GetDoubleFormatPattern() + "\")";
-        }
-      } else if (VariableHasType<string>(columnIndex)) {
-        valid = value != null;
-        if (!valid) {
-          errorMessage = "Invalid Value (string must not be null)";
-        }
-      } else if (VariableHasType<DateTime>(columnIndex)) {
-        DateTime date;
-        valid = DateTime.TryParse(value, out date);
-        if (!valid) {
-          errorMessage = "Invalid Value (Valid Value Format: \"" + CultureInfo.CurrentCulture.DateTimeFormat + "\"";
-        }
-      } else {
-        throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
-      }
-
-      return valid;
-    }
-
-    private void SetValueIfValid<T>(int columnIndex, int rowIndex, bool valid, T value) {
-      if (valid)
-        SetCell<T>(columnIndex, rowIndex, value);
-    }
-
-    public override bool AreAllStringColumns(IEnumerable<int> columnIndices) {
-      return columnIndices.All(x => VariableHasType<string>(x));
-    }
-
-    public override void InsertRow(int rowIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
-      foreach (IList column in variableValues) {
-        Type type = column.GetType().GetGenericArguments()[0];
-        column.Insert(rowIndex, type.IsValueType ? Activator.CreateInstance(type) : null);
-      }
-      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-        TrainingPartition.End++;
-        if (TrainingPartition.End <= TestPartition.Start) {
-          TestPartition.Start++;
-          TestPartition.End++;
-        }
-      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-        TestPartition.End++;
-        if (TestPartition.End <= TrainingPartition.Start) {
-          TestPartition.Start++;
-          TestPartition.End++;
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
-    }
-    public override void DeleteRow(int rowIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
-      foreach (IList column in variableValues) {
-        column.RemoveAt(rowIndex);
-      }
-      if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-        TrainingPartition.End--;
-        if (TrainingPartition.End <= TestPartition.Start) {
-          TestPartition.Start--;
-          TestPartition.End--;
-        }
-      } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-        TestPartition.End--;
-        if (TestPartition.End <= TrainingPartition.Start) {
-          TestPartition.Start--;
-          TestPartition.End--;
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
-    }
-    public override void DeleteRowsWithIndices(IEnumerable<int> rows) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, -1);
-      foreach (int rowIndex in rows.OrderByDescending(x => x)) {
-        foreach (IList column in variableValues) {
-          column.RemoveAt(rowIndex);
-        }
-        if (TrainingPartition.Start <= rowIndex && rowIndex <= TrainingPartition.End) {
-          TrainingPartition.End--;
-          if (TrainingPartition.End <= TestPartition.Start) {
-            TestPartition.Start--;
-            TestPartition.End--;
-          }
-        } else if (TestPartition.Start <= rowIndex && rowIndex <= TestPartition.End) {
-          TestPartition.End--;
-          if (TestPartition.End <= TrainingPartition.Start) {
-            TestPartition.Start--;
-            TestPartition.End--;
-          }
-        }
-      }
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, -1);
-    }
-
-    public override void InsertColumn<T>(string variableName, int columnIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
-      variableValues.Insert(columnIndex, new List<T>(Enumerable.Repeat(default(T), Rows)));
-      variableNames.Insert(columnIndex, variableName);
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
-    }
-
-    public override void DeleteColumn(int columnIndex) {
-      SaveSnapshot(DataPreprocessingChangedEventType.AddColumn, columnIndex, -1);
-      variableValues.RemoveAt(columnIndex);
-      variableNames.RemoveAt(columnIndex);
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.DeleteColumn, columnIndex, -1);
-    }
-
-    public override void RenameColumn(int columnIndex, string name) {
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, columnIndex, -1);
-      if (columnIndex < 0 || columnIndex > variableNames.Count)
-        throw new ArgumentOutOfRangeException("columnIndex");
-      variableNames[columnIndex] = name;
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-    }
-
-    public override void RenameColumns(IList<string> names) {
-      if (names == null) throw new ArgumentNullException("names");
-      if (names.Count != variableNames.Count) throw new ArgumentException("number of names must match the number of columns.", "names");
-
-      SaveSnapshot(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-      for (int i = 0; i < names.Count; i++)
-        variableNames[i] = names[i];
-
-      if (!IsInTransaction)
-        OnChanged(DataPreprocessingChangedEventType.ChangeColumn, -1, -1);
-    }
-
-    public override Dataset ExportToDataset() {
-      IList<IList> values = new List<IList>();
-
-      for (int i = 0; i < Columns; ++i) {
-        values.Add(variableValues[i]);
-      }
-
-      var dataset = new Dataset(variableNames, values);
-      return dataset;
-    }
-
-    public override void ClearSelection() {
-      Selection = new Dictionary<int, IList<int>>();
-    }
-
-    public override event EventHandler SelectionChanged;
-
-    protected override void OnSelectionChanged() {
-      var listeners = SelectionChanged;
-      if (listeners != null) listeners(this, EventArgs.Empty);
-    }
-    #endregion
-
-    #region TransactionalPreprocessingData members
-    public bool IsUndoAvailable {
-      get { return undoHistory.Count > 0; }
-    }
-
-    public void Undo() {
-      if (IsUndoAvailable) {
-        Snapshot previousSnapshot = undoHistory[undoHistory.Count - 1];
-        variableValues = previousSnapshot.VariableValues;
-        variableNames = previousSnapshot.VariableNames;
-        TrainingPartition = previousSnapshot.TrainingPartition;
-        TestPartition = previousSnapshot.TestPartition;
-        Transformations = previousSnapshot.Transformations;
-        undoHistory.Remove(previousSnapshot);
-        OnChanged(previousSnapshot.ChangedType,
-          previousSnapshot.ChangedColumn,
-          previousSnapshot.ChangedRow);
-      }
-    }
-
-    public void InTransaction(Action action, DataPreprocessingChangedEventType type = DataPreprocessingChangedEventType.Any) {
-      BeginTransaction(type);
-      action();
-      EndTransaction();
-    }
-
-    public void BeginTransaction(DataPreprocessingChangedEventType type) {
-      SaveSnapshot(type, -1, -1);
-      eventStack.Push(type);
-    }
-
-    public void EndTransaction() {
-      if (eventStack.Count == 0)
-        throw new InvalidOperationException("There is no open transaction that can be ended.");
-
-      var @event = eventStack.Pop();
-      OnChanged(@event, -1, -1);
-    }
-    #endregion
-  }
-}
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Filter/ComparisonFilter.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Filter/ComparisonFilter.cs	(revision 15535)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Filter/ComparisonFilter.cs	(revision 15535)
@@ -0,0 +1,140 @@
+﻿#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;
+using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Common.Resources;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.DataPreprocessing.Filter {
+  [Item("ComparisonFilter", "A filter which compares the member of the preprocessing data with the constraint data.")]
+  public class ComparisonFilter : ComparisonConstraint, IFilter {
+    public override string ItemName {
+      get { return "ComparisonFilter"; }
+    }
+
+    public override Image ItemImage {
+      get { return VSImageLibrary.Filter; }
+    }
+
+    public new IPreprocessingData ConstrainedValue {
+      get { return (IPreprocessingData)base.ConstrainedValue; }
+      set { base.ConstrainedValue = value; }
+    }
+
+    public new IStringConvertibleValue ConstraintData {
+      get { return (IStringConvertibleValue)base.ConstraintData; }
+      set {
+        if (!(value is IComparable))
+          throw new ArgumentException("Only IComparables allowed for ConstraintData");
+        base.ConstraintData = value;
+      }
+    }
+
+    public ComparisonFilter() : base() { }
+    protected ComparisonFilter(bool deserializing) : base(deserializing) { }
+
+    public ComparisonFilter(IPreprocessingData constrainedValue, ConstraintOperation constraintOperation, object constraintData)
+      : base(constrainedValue, constraintOperation, constraintData) {
+    }
+
+    public ComparisonFilter(IPreprocessingData constrainedValue, ConstraintOperation constraintOperation, object constraintData, bool active)
+      : base(constrainedValue, constraintOperation, constraintData, active) {
+    }
+
+    protected ComparisonFilter(ComparisonFilter original, Cloner cloner)
+      : base(original, cloner) {
+      constraintColumn = original.constraintColumn;
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ComparisonFilter(this, cloner);
+    }
+
+    private int constraintColumn;
+    public int ConstraintColumn {
+      get { return constraintColumn; }
+      set {
+        if (ConstrainedValue.Columns < value)
+          throw new ArgumentException("Could not set ConstraintData to not existing column index.");
+
+        if (constraintColumn != value) {
+          constraintColumn = value;
+          this.OnConstraintColumnChanged();
+          this.OnToStringChanged();
+        }
+      }
+    }
+
+    // return remaining rows
+    public new bool[] Check() {
+      bool[] result = new bool[ConstrainedValue.Rows];
+
+      if (!Active)
+        return result;
+
+      for (int row = 0; row < ConstrainedValue.Rows; ++row) {
+        object item = null;
+        if (ConstrainedValue.VariableHasType<double>(constraintColumn)) {
+          item = new HeuristicLab.Data.DoubleValue(ConstrainedValue.GetCell<double>(ConstraintColumn, row));
+        } else if (ConstrainedValue.VariableHasType<DateTime>(constraintColumn)) {
+          item = new HeuristicLab.Data.DateTimeValue(ConstrainedValue.GetCell<DateTime>(ConstraintColumn, row));
+        } else {
+          item = new StringValue(ConstrainedValue.GetCell<string>(ConstraintColumn, row));
+        }
+
+        result[row] = base.Check(item);
+      }
+
+      return result;
+    }
+
+    public new bool[] Check(out string errorMessage) {
+      errorMessage = string.Empty;
+      return this.Check();
+    }
+
+    public override string ToString() {
+      string s = string.Empty;
+      if (ConstrainedValue != null)
+        s += ConstrainedValue.GetVariableName(ConstraintColumn) + " ";
+
+      if (ConstraintOperation != null)
+        s += ConstraintOperation.ToString() + " ";
+
+      if (ConstraintData != null)
+        s += ConstraintData.ToString();
+      else
+        s += "null";
+
+      s += ".";
+      return s;
+    }
+
+    public event EventHandler ConstraintColumnChanged;
+    protected virtual void OnConstraintColumnChanged() {
+      EventHandler handler = ConstraintColumnChanged;
+      if (handler != null)
+        handler(this, EventArgs.Empty);
+    }
+  }
+}
Index: /stable/HeuristicLab.DataPreprocessing/3.4/Filter/IFilter.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/Filter/IFilter.cs	(revision 15535)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/Filter/IFilter.cs	(revision 15535)
@@ -0,0 +1,29 @@
+﻿#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 HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing.Filter {
+  public interface IFilter : IConstraint {
+    new bool[] Check();
+    new bool[] Check(out string errorMessage);
+  }
+}
Index: /stable/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 15535)
@@ -79,4 +79,5 @@
   <ItemGroup>
     <Compile Include="Content\MultiScatterPlotContent.cs" />
+    <Compile Include="Content\PreprocessingContent.cs" />
     <Compile Include="Content\SingleScatterPlotContent.cs" />
     <Compile Include="Content\ScatterPlotContent.cs" />
@@ -90,10 +91,8 @@
     <Compile Include="PreprocessingTransformator.cs" />
     <Compile Include="Data\DataPreprocessingChangedEvent.cs" />
-    <Compile Include="Logic\Filter\ComparisonFilter.cs" />
-    <Compile Include="Logic\Filter\IFilter.cs" />
-    <Compile Include="Logic\ManipulationLogic.cs" />
+    <Compile Include="Filter\ComparisonFilter.cs" />
+    <Compile Include="Filter\IFilter.cs" />
     <Compile Include="Data\IPreprocessingData.cs" />
     <Compile Include="Content\FilterContent.cs" />
-    <Compile Include="Logic\FilterLogic.cs" />
     <Compile Include="Content\HistogramContent.cs" />
     <Compile Include="Content\LineChartContent.cs" />
@@ -105,8 +104,4 @@
     <Compile Include="Content\DataGridContent.cs" />
     <Compile Include="PreprocessingContext.cs" />
-    <Compile Include="Data\TransactionalPreprocessingData.cs" />
-    <Compile Include="Logic\SearchLogic.cs" />
-    <Compile Include="Logic\StatisticsLogic.cs" />
-    <Compile Include="Data\ITransactionalPreprocessingData.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
Index: /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 15535)
@@ -71,5 +71,5 @@
       if (namedSource != null)
         Name = "Preprocessing " + namedSource.Name;
-      Data = new FilteredPreprocessingData(new TransactionalPreprocessingData(problemData));
+      Data = new FilteredPreprocessingData(new PreprocessingData(problemData));
       OnReset();
       // Reset GUI:
Index: /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs
===================================================================
--- /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15534)
+++ /stable/HeuristicLab.DataPreprocessing/3.4/PreprocessingTransformator.cs	(revision 15535)
@@ -29,5 +29,5 @@
 namespace HeuristicLab.DataPreprocessing {
   public class PreprocessingTransformator {
-    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly IPreprocessingData preprocessingData;
 
     private readonly IDictionary<string, IList<double>> originalColumns;
@@ -36,5 +36,5 @@
 
     public PreprocessingTransformator(IPreprocessingData preprocessingData) {
-      this.preprocessingData = (ITransactionalPreprocessingData)preprocessingData;
+      this.preprocessingData = preprocessingData;
       originalColumns = new Dictionary<string, IList<double>>();
       renamedColumns = new Dictionary<string, string>();
@@ -68,10 +68,8 @@
           preprocessingData.Undo();
         }
-      }
-      catch (Exception e) {
+      } catch (Exception e) {
         preprocessingData.Undo();
         if (string.IsNullOrEmpty(errorMsg)) errorMsg = e.Message;
-      }
-      finally {
+      } finally {
         preprocessingData.EndTransaction();
       }
