Index: /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.cs	(revision 13508)
@@ -21,6 +21,6 @@
 
 using System;
-using System.Collections.Generic;
-using System.Linq;
+using System.IO;
+using System.Threading.Tasks;
 using System.Windows.Forms;
 using HeuristicLab.Common;
@@ -28,4 +28,7 @@
 using HeuristicLab.Core.Views;
 using HeuristicLab.MainForm;
+using HeuristicLab.Problems.DataAnalysis;
+using HeuristicLab.Problems.Instances.DataAnalysis;
+using HeuristicLab.Problems.Instances.DataAnalysis.Views;
 
 namespace HeuristicLab.DataPreprocessing.Views {
@@ -68,20 +71,28 @@
 
         viewShortcutListView.Content = viewShortcuts.AsReadOnly();
-
         viewShortcutListView.ItemsListView.Items[0].Selected = true;
         viewShortcutListView.Select();
 
-        applyComboBox.Items.Clear();
-        applyComboBox.DataSource = Content.ExportPossibilities.ToList();
-        applyComboBox.DisplayMember = "Key";
-        if (applyComboBox.Items.Count > 0)
-          applyComboBox.SelectedIndex = 0;
+        applyTypeContextMenuStrip.Items.Clear();
+        exportTypeContextMenuStrip.Items.Clear();
+        foreach (var exportOption in Content.GetSourceExportOptions()) {
+          var applyMenuItem = new ToolStripMenuItem(exportOption.Key) { Tag = exportOption.Value };
+          applyMenuItem.Click += applyToolStripMenuItem_Click;
+          applyTypeContextMenuStrip.Items.Add(applyMenuItem);
+
+          var exportMenuItem = new ToolStripMenuItem(exportOption.Key) { Tag = exportOption.Value };
+          exportMenuItem.Click += exportToolStripMenuItem_Click;
+          exportTypeContextMenuStrip.Items.Add(exportMenuItem);
+        }
+        var exportCsvMenuItem = new ToolStripMenuItem(".csv");
+        exportCsvMenuItem.Click += exportCsvMenuItem_Click;
+        exportTypeContextMenuStrip.Items.Add(exportCsvMenuItem);
       } else {
         viewShortcutListView.Content = null;
       }
     }
-
     protected override void RegisterContentEvents() {
       base.RegisterContentEvents();
+      Content.Reset += Content_Reset;
       Content.Data.FilterChanged += Data_FilterChanged;
     }
@@ -89,5 +100,10 @@
     protected override void DeregisterContentEvents() {
       base.DeregisterContentEvents();
+      Content.Reset -= Content_Reset;
       Content.Data.FilterChanged -= Data_FilterChanged;
+    }
+
+    void Content_Reset(object sender, EventArgs e) {
+      OnContentChanged(); // Reset by setting new content
     }
 
@@ -104,8 +120,87 @@
     }
 
+    #region New
+    private void newButton_Click(object sender, EventArgs e) {
+      newProblemDataTypeContextMenuStrip.Show(Cursor.Position);
+    }
+    private void newRegressionToolStripMenuItem_Click(object sender, EventArgs e) {
+      Content.Import(new RegressionProblemData());
+    }
+    private void newClassificationToolStripMenuItem_Click(object sender, EventArgs e) {
+      Content.Import(new ClassificationProblemData());
+    }
+    private void newTimeSeriesToolStripMenuItem_Click(object sender, EventArgs e) {
+      Content.Import(new TimeSeriesPrognosisProblemData());
+    }
+    #endregion
+
+    #region Import
+    private void importButton_Click(object sender, EventArgs e) {
+      importProblemDataTypeContextMenuStrip.Show(Cursor.Position);
+    }
+    private void importRegressionToolStripMenuItem_Click(object sender, EventArgs e) {
+      Import(new RegressionCSVInstanceProvider(), new RegressionImportTypeDialog(),
+        (dialog => ((RegressionImportTypeDialog)dialog).ImportType));
+    }
+    private void importClassificationToolStripMenuItem_Click(object sender, EventArgs e) {
+      Import(new ClassificationCSVInstanceProvider(), new ClassificationImportTypeDialog(),
+        (dialog => ((ClassificationImportTypeDialog)dialog).ImportType));
+    }
+    private void importTimeSeriesToolStripMenuItem_Click(object sender, EventArgs e) {
+      Import(new TimeSeriesPrognosisCSVInstanceProvider(), new TimeSeriesPrognosisImportTypeDialog(),
+        (dialog => ((TimeSeriesPrognosisImportTypeDialog)dialog).ImportType));
+    }
+    private void Import<TProblemData, TImportType>(DataAnalysisInstanceProvider<TProblemData, TImportType> instanceProvider, DataAnalysisImportTypeDialog importTypeDialog,
+      Func<DataAnalysisImportTypeDialog, TImportType> getImportType)
+      where TProblemData : class, IDataAnalysisProblemData
+      where TImportType : DataAnalysisImportType {
+      if (importTypeDialog.ShowDialog() == DialogResult.OK) {
+        Task.Run(() => {
+          TProblemData instance;
+          var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
+          // lock active view and show progress bar
+          var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
+
+          try {
+            var progress = mainForm.AddOperationProgressToContent(activeView.Content, "Loading problem instance.");
+
+            instanceProvider.ProgressChanged += (o, args) => { progress.ProgressValue = args.ProgressPercentage / 100.0; };
+
+            instance = instanceProvider.ImportData(importTypeDialog.Path, getImportType(importTypeDialog), importTypeDialog.CSVFormat);
+          } catch (IOException ex) {
+            MessageBox.Show(string.Format("There was an error parsing the file: {0}", Environment.NewLine + ex.Message), "Error while parsing", MessageBoxButtons.OK, MessageBoxIcon.Error);
+            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            return;
+          }
+          try {
+            Content.Import(instance);
+          } catch (IOException ex) {
+            MessageBox.Show(string.Format("This problem does not support loading the instance {0}: {1}", Path.GetFileName(importTypeDialog.Path), Environment.NewLine + ex.Message), "Cannot load instance");
+          } finally {
+            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+          }
+        });
+      }
+    }
+    #endregion
+
+    #region Apply
+    private void applyInNewTabButton_Click(object sender, EventArgs e) {
+      applyTypeContextMenuStrip.Show(Cursor.Position);
+    }
+    private void applyToolStripMenuItem_Click(object sender, EventArgs e) {
+      var menuItem = (ToolStripMenuItem)sender;
+      var itemCreator = (Func<IItem>)menuItem.Tag;
+      MainFormManager.MainForm.ShowContent(itemCreator());
+    }
+    #endregion
+
+    #region Export
     private void exportProblemButton_Click(object sender, EventArgs e) {
-      var exportOption = (KeyValuePair<string, Func<IItem>>)applyComboBox.SelectedItem;
-      var exportItem = exportOption.Value();
-
+      exportTypeContextMenuStrip.Show(Cursor.Position);
+    }
+    private void exportToolStripMenuItem_Click(object sender, EventArgs e) {
+      var menuItem = (ToolStripMenuItem)sender;
+      var itemCreator = (Func<IItem>)menuItem.Tag;
       var saveFileDialog = new SaveFileDialog {
         Title = "Save Item",
@@ -115,21 +210,60 @@
       };
 
-      var content = exportItem as IStorableContent;
       if (saveFileDialog.ShowDialog() == DialogResult.OK) {
-        bool compressed = saveFileDialog.FilterIndex != 1;
-        ContentManager.Save(content, saveFileDialog.FileName, compressed);
-      }
-    }
-
-    private void applyInNewTabButton_Click(object sender, EventArgs e) {
-      var exportOption = (KeyValuePair<string, Func<IItem>>)applyComboBox.SelectedItem;
-      var exportItem = exportOption.Value();
-
-      MainFormManager.MainForm.ShowContent(exportItem);
-    }
-
+        Task.Run(() => {
+          bool compressed = saveFileDialog.FilterIndex != 1;
+          var storable = itemCreator() as IStorableContent;
+          if (storable != null) {
+            var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
+            var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
+            try {
+              mainForm.AddOperationProgressToContent(activeView.Content, "Exporting data.");
+              ContentManager.Save(storable, saveFileDialog.FileName, compressed);
+            } finally {
+              mainForm.RemoveOperationProgressFromContent(activeView.Content);
+            }
+          }
+        });
+      }
+    }
+    private void exportCsvMenuItem_Click(object sender, EventArgs e) {
+      var saveFileDialog = new SaveFileDialog {
+        Title = "Save Data",
+        DefaultExt = "csv",
+        Filter = "CSV files|*.csv|All files|*.*",
+        FilterIndex = 1
+      };
+
+      if (saveFileDialog.ShowDialog() == DialogResult.OK) {
+        Task.Run(() => {
+          var mainForm = (MainForm.WindowsForms.MainForm)MainFormManager.MainForm;
+          var activeView = (IContentView)MainFormManager.MainForm.ActiveView;
+          try {
+            var problemData = Content.CreateNewProblemData();
+            mainForm.AddOperationProgressToContent(activeView.Content, "Exporting data.");
+            if (problemData is TimeSeriesPrognosisProblemData)
+              Export(new TimeSeriesPrognosisCSVInstanceProvider(), problemData, saveFileDialog.FileName);
+            else if (problemData is RegressionProblemData)
+              Export(new RegressionCSVInstanceProvider(), problemData, saveFileDialog.FileName);
+            else if (problemData is ClassificationProblemData)
+              Export(new ClassificationCSVInstanceProvider(), problemData, saveFileDialog.FileName);
+          } finally {
+            mainForm.RemoveOperationProgressFromContent(activeView.Content);
+          }
+        });
+      }
+    }
+    private void Export<TProblemData, TImportType>(DataAnalysisInstanceProvider<TProblemData, TImportType> instanceProvider,
+      IDataAnalysisProblemData problemData, string path)
+      where TProblemData : class, IDataAnalysisProblemData where TImportType : DataAnalysisImportType {
+      instanceProvider.ExportData((TProblemData)problemData, path);
+    }
+    #endregion
+
+    #region Undo / Redo
     private void undoButton_Click(object sender, EventArgs e) {
       Content.Data.Undo();
     }
+    #endregion
   }
 }
Index: /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.designer.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.designer.cs	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessingView.designer.cs	(revision 13508)
@@ -45,4 +45,5 @@
     /// </summary>
     private void InitializeComponent() {
+      this.components = new System.ComponentModel.Container();
       System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DataPreprocessingView));
       this.undoButton = new System.Windows.Forms.Button();
@@ -50,9 +51,21 @@
       this.exportProblemButton = new System.Windows.Forms.Button();
       this.lblFilterActive = new System.Windows.Forms.Label();
-      this.applyComboBox = new System.Windows.Forms.ComboBox();
-      this.exportLabel = new System.Windows.Forms.Label();
       this.redoButton = new System.Windows.Forms.Button();
+      this.newButton = new System.Windows.Forms.Button();
+      this.importButton = new System.Windows.Forms.Button();
+      this.newProblemDataTypeContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+      this.newRegressionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.newClassificationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.newTimeSeriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.importProblemDataTypeContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+      this.importRegressionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.importClassificationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+      this.importTimeSeriesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
       this.viewShortcutListView = new HeuristicLab.DataPreprocessing.Views.ViewShortcutListView();
+      this.applyTypeContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
+      this.exportTypeContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).BeginInit();
+      this.newProblemDataTypeContextMenuStrip.SuspendLayout();
+      this.importProblemDataTypeContextMenuStrip.SuspendLayout();
       this.SuspendLayout();
       // 
@@ -70,5 +83,5 @@
       // 
       this.undoButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Undo;
-      this.undoButton.Location = new System.Drawing.Point(6, 56);
+      this.undoButton.Location = new System.Drawing.Point(131, 26);
       this.undoButton.Name = "undoButton";
       this.undoButton.Size = new System.Drawing.Size(24, 24);
@@ -81,5 +94,5 @@
       // 
       this.applyInNewTabButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Play;
-      this.applyInNewTabButton.Location = new System.Drawing.Point(57, 26);
+      this.applyInNewTabButton.Location = new System.Drawing.Point(69, 26);
       this.applyInNewTabButton.Name = "applyInNewTabButton";
       this.applyInNewTabButton.Size = new System.Drawing.Size(24, 24);
@@ -91,10 +104,10 @@
       // exportProblemButton
       // 
-      this.exportProblemButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Save;
-      this.exportProblemButton.Location = new System.Drawing.Point(87, 26);
+      this.exportProblemButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.SaveAs;
+      this.exportProblemButton.Location = new System.Drawing.Point(99, 26);
       this.exportProblemButton.Name = "exportProblemButton";
       this.exportProblemButton.Size = new System.Drawing.Size(24, 24);
       this.exportProblemButton.TabIndex = 3;
-      this.toolTip.SetToolTip(this.exportProblemButton, "Save");
+      this.toolTip.SetToolTip(this.exportProblemButton, "Export to File");
       this.exportProblemButton.UseVisualStyleBackColor = true;
       this.exportProblemButton.Click += new System.EventHandler(this.exportProblemButton_Click);
@@ -103,5 +116,5 @@
       // 
       this.lblFilterActive.AutoSize = true;
-      this.lblFilterActive.Location = new System.Drawing.Point(84, 62);
+      this.lblFilterActive.Location = new System.Drawing.Point(203, 31);
       this.lblFilterActive.Name = "lblFilterActive";
       this.lblFilterActive.Size = new System.Drawing.Size(277, 13);
@@ -110,33 +123,9 @@
       this.lblFilterActive.Visible = false;
       // 
-      // applyComboBox
-      // 
-      this.applyComboBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
-            | System.Windows.Forms.AnchorStyles.Right)));
-      this.applyComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
-      this.applyComboBox.FormattingEnabled = true;
-      this.applyComboBox.Items.AddRange(new object[] {
-            "Algorithm",
-            "Problem",
-            "ProblemData"});
-      this.applyComboBox.Location = new System.Drawing.Point(117, 28);
-      this.applyComboBox.Name = "applyComboBox";
-      this.applyComboBox.Size = new System.Drawing.Size(696, 21);
-      this.applyComboBox.TabIndex = 4;
-      // 
-      // exportLabel
-      // 
-      this.exportLabel.AutoSize = true;
-      this.exportLabel.Location = new System.Drawing.Point(5, 31);
-      this.exportLabel.Name = "exportLabel";
-      this.exportLabel.Size = new System.Drawing.Size(40, 13);
-      this.exportLabel.TabIndex = 8;
-      this.exportLabel.Text = "Export:";
-      // 
       // redoButton
       // 
       this.redoButton.Enabled = false;
       this.redoButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Redo;
-      this.redoButton.Location = new System.Drawing.Point(36, 56);
+      this.redoButton.Location = new System.Drawing.Point(161, 26);
       this.redoButton.Name = "redoButton";
       this.redoButton.Size = new System.Drawing.Size(24, 24);
@@ -145,4 +134,84 @@
       this.redoButton.UseVisualStyleBackColor = true;
       // 
+      // newButton
+      // 
+      this.newButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.NewDocument;
+      this.newButton.Location = new System.Drawing.Point(6, 26);
+      this.newButton.Name = "newButton";
+      this.newButton.Size = new System.Drawing.Size(24, 24);
+      this.newButton.TabIndex = 3;
+      this.newButton.UseVisualStyleBackColor = true;
+      this.newButton.Click += new System.EventHandler(this.newButton_Click);
+      // 
+      // importButton
+      // 
+      this.importButton.Image = HeuristicLab.Common.Resources.VSImageLibrary.Open;
+      this.importButton.Location = new System.Drawing.Point(36, 26);
+      this.importButton.Name = "importButton";
+      this.importButton.Size = new System.Drawing.Size(24, 24);
+      this.importButton.TabIndex = 3;
+      this.importButton.UseVisualStyleBackColor = true;
+      this.importButton.Click += new System.EventHandler(this.importButton_Click);
+      // 
+      // newProblemDataTypeContextMenuStrip
+      // 
+      this.newProblemDataTypeContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.newRegressionToolStripMenuItem,
+            this.newClassificationToolStripMenuItem,
+            this.newTimeSeriesToolStripMenuItem});
+      this.newProblemDataTypeContextMenuStrip.Name = "newProblemDataTypeContextMenuStrip";
+      this.newProblemDataTypeContextMenuStrip.Size = new System.Drawing.Size(190, 70);
+      // 
+      // newRegressionToolStripMenuItem
+      // 
+      this.newRegressionToolStripMenuItem.Name = "newRegressionToolStripMenuItem";
+      this.newRegressionToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.newRegressionToolStripMenuItem.Text = "Regression";
+      this.newRegressionToolStripMenuItem.Click += new System.EventHandler(this.newRegressionToolStripMenuItem_Click);
+      // 
+      // newClassificationToolStripMenuItem
+      // 
+      this.newClassificationToolStripMenuItem.Name = "newClassificationToolStripMenuItem";
+      this.newClassificationToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.newClassificationToolStripMenuItem.Text = "Classification";
+      this.newClassificationToolStripMenuItem.Click += new System.EventHandler(this.newClassificationToolStripMenuItem_Click);
+      // 
+      // newTimeSeriesToolStripMenuItem
+      // 
+      this.newTimeSeriesToolStripMenuItem.Name = "newTimeSeriesToolStripMenuItem";
+      this.newTimeSeriesToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.newTimeSeriesToolStripMenuItem.Text = "Time Series Prognosis";
+      this.newTimeSeriesToolStripMenuItem.Click += new System.EventHandler(this.newTimeSeriesToolStripMenuItem_Click);
+      // 
+      // importProblemDataTypeContextMenuStrip
+      // 
+      this.importProblemDataTypeContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+            this.importRegressionToolStripMenuItem,
+            this.importClassificationToolStripMenuItem,
+            this.importTimeSeriesToolStripMenuItem});
+      this.importProblemDataTypeContextMenuStrip.Name = "newProblemDataTypeContextMenuStrip";
+      this.importProblemDataTypeContextMenuStrip.Size = new System.Drawing.Size(190, 92);
+      // 
+      // importRegressionToolStripMenuItem
+      // 
+      this.importRegressionToolStripMenuItem.Name = "importRegressionToolStripMenuItem";
+      this.importRegressionToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.importRegressionToolStripMenuItem.Text = "Regression";
+      this.importRegressionToolStripMenuItem.Click += new System.EventHandler(this.importRegressionToolStripMenuItem_Click);
+      // 
+      // importClassificationToolStripMenuItem
+      // 
+      this.importClassificationToolStripMenuItem.Name = "importClassificationToolStripMenuItem";
+      this.importClassificationToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.importClassificationToolStripMenuItem.Text = "Classification";
+      this.importClassificationToolStripMenuItem.Click += new System.EventHandler(this.importClassificationToolStripMenuItem_Click);
+      // 
+      // importTimeSeriesToolStripMenuItem
+      // 
+      this.importTimeSeriesToolStripMenuItem.Name = "importTimeSeriesToolStripMenuItem";
+      this.importTimeSeriesToolStripMenuItem.Size = new System.Drawing.Size(189, 22);
+      this.importTimeSeriesToolStripMenuItem.Text = "Time Series Prognosis";
+      this.importTimeSeriesToolStripMenuItem.Click += new System.EventHandler(this.importTimeSeriesToolStripMenuItem_Click);
+      // 
       // viewShortcutListView
       // 
@@ -152,9 +221,19 @@
       this.viewShortcutListView.Caption = "ViewShortcutCollection View";
       this.viewShortcutListView.Content = null;
-      this.viewShortcutListView.Location = new System.Drawing.Point(4, 86);
+      this.viewShortcutListView.Location = new System.Drawing.Point(4, 56);
       this.viewShortcutListView.Name = "viewShortcutListView";
       this.viewShortcutListView.ReadOnly = false;
-      this.viewShortcutListView.Size = new System.Drawing.Size(831, 360);
+      this.viewShortcutListView.Size = new System.Drawing.Size(831, 390);
       this.viewShortcutListView.TabIndex = 7;
+      // 
+      // applyTypeContextMenuStrip
+      // 
+      this.applyTypeContextMenuStrip.Name = "newProblemDataTypeContextMenuStrip";
+      this.applyTypeContextMenuStrip.Size = new System.Drawing.Size(61, 4);
+      // 
+      // exportTypeContextMenuStrip
+      // 
+      this.exportTypeContextMenuStrip.Name = "newProblemDataTypeContextMenuStrip";
+      this.exportTypeContextMenuStrip.Size = new System.Drawing.Size(61, 4);
       // 
       // DataPreprocessingView
@@ -162,26 +241,28 @@
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-      this.Controls.Add(this.applyComboBox);
-      this.Controls.Add(this.exportLabel);
+      this.Controls.Add(this.newButton);
+      this.Controls.Add(this.importButton);
+      this.Controls.Add(this.applyInNewTabButton);
       this.Controls.Add(this.exportProblemButton);
-      this.Controls.Add(this.applyInNewTabButton);
+      this.Controls.Add(this.undoButton);
+      this.Controls.Add(this.redoButton);
       this.Controls.Add(this.lblFilterActive);
       this.Controls.Add(this.viewShortcutListView);
-      this.Controls.Add(this.redoButton);
-      this.Controls.Add(this.undoButton);
       this.Name = "DataPreprocessingView";
       this.Size = new System.Drawing.Size(838, 449);
-      this.Controls.SetChildIndex(this.undoButton, 0);
-      this.Controls.SetChildIndex(this.redoButton, 0);
       this.Controls.SetChildIndex(this.viewShortcutListView, 0);
       this.Controls.SetChildIndex(this.lblFilterActive, 0);
+      this.Controls.SetChildIndex(this.redoButton, 0);
+      this.Controls.SetChildIndex(this.undoButton, 0);
+      this.Controls.SetChildIndex(this.exportProblemButton, 0);
+      this.Controls.SetChildIndex(this.applyInNewTabButton, 0);
+      this.Controls.SetChildIndex(this.importButton, 0);
+      this.Controls.SetChildIndex(this.newButton, 0);
+      this.Controls.SetChildIndex(this.infoLabel, 0);
+      this.Controls.SetChildIndex(this.nameTextBox, 0);
       this.Controls.SetChildIndex(this.nameLabel, 0);
-      this.Controls.SetChildIndex(this.nameTextBox, 0);
-      this.Controls.SetChildIndex(this.infoLabel, 0);
-      this.Controls.SetChildIndex(this.applyInNewTabButton, 0);
-      this.Controls.SetChildIndex(this.exportProblemButton, 0);
-      this.Controls.SetChildIndex(this.exportLabel, 0);
-      this.Controls.SetChildIndex(this.applyComboBox, 0);
       ((System.ComponentModel.ISupportInitialize)(this.errorProvider)).EndInit();
+      this.newProblemDataTypeContextMenuStrip.ResumeLayout(false);
+      this.importProblemDataTypeContextMenuStrip.ResumeLayout(false);
       this.ResumeLayout(false);
       this.PerformLayout();
@@ -196,7 +277,17 @@
     private ViewShortcutListView viewShortcutListView;
     private System.Windows.Forms.Label lblFilterActive;
-    private System.Windows.Forms.Label exportLabel;
     private System.Windows.Forms.Button redoButton;
-    private System.Windows.Forms.ComboBox applyComboBox;
+    private System.Windows.Forms.Button newButton;
+    private System.Windows.Forms.Button importButton;
+    private System.Windows.Forms.ContextMenuStrip newProblemDataTypeContextMenuStrip;
+    private System.Windows.Forms.ToolStripMenuItem newRegressionToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem newClassificationToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem newTimeSeriesToolStripMenuItem;
+    private System.Windows.Forms.ContextMenuStrip importProblemDataTypeContextMenuStrip;
+    private System.Windows.Forms.ToolStripMenuItem importRegressionToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem importClassificationToolStripMenuItem;
+    private System.Windows.Forms.ToolStripMenuItem importTimeSeriesToolStripMenuItem;
+    private System.Windows.Forms.ContextMenuStrip applyTypeContextMenuStrip;
+    private System.Windows.Forms.ContextMenuStrip exportTypeContextMenuStrip;
   }
 }
Index: /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessorStarter.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessorStarter.cs	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/DataPreprocessorStarter.cs	(revision 13508)
@@ -34,5 +34,5 @@
       IDataAnalysisProblem problem;
       GetMostOuterContent(currentView as Control, out algorithm, out problem);
-      var context = new PreprocessingContext(algorithm ?? problem ?? problemData as IItem);
+      var context = new PreprocessingContext(problemData, algorithm ?? problem ?? problemData as IItem);
       MainFormManager.MainForm.ShowContent(context);
     }
Index: /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/HeuristicLab.DataPreprocessing.Views-3.4.csproj	(revision 13508)
@@ -255,4 +255,5 @@
       <Project>{958b43bc-cc5c-4fa2-8628-2b3b01d890b6}</Project>
       <Name>HeuristicLab.Collections-3.3</Name>
+      <Private>False</Private>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.Common.Resources\3.3\HeuristicLab.Common.Resources-3.3.csproj">
@@ -309,4 +310,5 @@
       <Project>{C664305E-497C-4533-A140-967DEDB05C19}</Project>
       <Name>HeuristicLab.Optimizer-3.3</Name>
+      <Private>False</Private>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
@@ -323,4 +325,19 @@
       <Project>{df87c13e-a889-46ff-8153-66dcaa8c5674}</Project>
       <Name>HeuristicLab.Problems.DataAnalysis-3.4</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances.DataAnalysis.Views\3.3\HeuristicLab.Problems.Instances.DataAnalysis.Views-3.3.csproj">
+      <Project>{72232235-B6CF-4E6C-B086-9E9E11AA0717}</Project>
+      <Name>HeuristicLab.Problems.Instances.DataAnalysis.Views-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances.DataAnalysis\3.3\HeuristicLab.Problems.Instances.DataAnalysis-3.3.csproj">
+      <Project>{94C7714E-29D4-4D6D-B213-2C18D627AB75}</Project>
+      <Name>HeuristicLab.Problems.Instances.DataAnalysis-3.3</Name>
+      <Private>False</Private>
+    </ProjectReference>
+    <ProjectReference Include="..\..\HeuristicLab.Problems.Instances\3.3\HeuristicLab.Problems.Instances-3.3.csproj">
+      <Project>{3540E29E-4793-49E7-8EE2-FEA7F61C3994}</Project>
+      <Name>HeuristicLab.Problems.Instances-3.3</Name>
       <Private>False</Private>
     </ProjectReference>
Index: /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/Plugin.cs.frame
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/Plugin.cs.frame	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing.Views/3.4/Plugin.cs.frame	(revision 13508)
@@ -44,4 +44,7 @@
   [PluginDependency("HeuristicLab.Problems.DataAnalysis", "3.4")]
   [PluginDependency("HeuristicLab.Problems.DataAnalysis.Views", "3.4")]
+  [PluginDependency("HeuristicLab.Problems.Instances", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances.DataAnalysis", "3.3")]
+  [PluginDependency("HeuristicLab.Problems.Instances.DataAnalysis.Views", "3.3")]
   [PluginDependency("HeuristicLab.Visualization.ChartControlsExtensions", "3.3")]
   public class HeuristicLabDataPreprocessingViewPlugin : PluginBase {
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/CorrelationMatrixContent.cs	(revision 13508)
@@ -0,0 +1,65 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("Feature Correlation Matrix", "Represents the feature correlation matrix.")]
+  public class CorrelationMatrixContent : Item, IViewChartShortcut {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Gradient; }
+    }
+
+    private PreprocessingContext Context { get; set; }
+    private ITransactionalPreprocessingData PreprocessingData {
+      get { return Context.Data; }
+    }
+
+    public DataAnalysisProblemData ProblemData {
+      get {
+        return (DataAnalysisProblemData)Context.CreateNewProblemData();
+        //var creator = new ProblemDataCreator(Context);
+        //return (DataAnalysisProblemData)creator.CreateProblemData();
+      }
+    }
+
+    public CorrelationMatrixContent(PreprocessingContext context) {
+      Context = context;
+    }
+
+    public CorrelationMatrixContent(CorrelationMatrixContent original, Cloner cloner)
+      : base(original, cloner) {
+      Context = original.Context;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new CorrelationMatrixContent(this, cloner);
+    }
+
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { PreprocessingData.Changed += value; }
+      remove { PreprocessingData.Changed -= value; }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataCompletenessChartContent.cs	(revision 13508)
@@ -0,0 +1,29 @@
+﻿using System.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("DataCompletenessChart", "Represents a datacompleteness chart.")]
+
+  public class DataCompletenessChartContent : Item, IViewChartShortcut {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.EditBrightnessContrast; }
+    }
+
+    //public DataGridLogic DataGridLogic { get; private set; }
+    public SearchLogic SearchLogic { get; private set; }
+
+    public DataCompletenessChartContent(SearchLogic searchLogic) {
+      SearchLogic = searchLogic;
+    }
+
+    public DataCompletenessChartContent(DataCompletenessChartContent content, Cloner cloner)
+      : base(content, cloner) {
+      SearchLogic = content.SearchLogic;
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataCompletenessChartContent(this, cloner);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/DataGridContent.cs	(revision 13508)
@@ -0,0 +1,160 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+
+  [Item("DataGrid", "Represents a data grid.")]
+  public class DataGridContent : Item, IViewShortcut, IDataGridContent {
+
+    public ITransactionalPreprocessingData PreProcessingData { get; private set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Table; }
+    }
+
+    public ManipulationLogic ManipulationLogic { get; private set; }
+    public FilterLogic FilterLogic { get; private set; }
+
+    public int Rows {
+      get {
+        return PreProcessingData.Rows;
+      }
+      set {
+        //does nothing
+      }
+    }
+
+    public int Columns {
+      get {
+        return PreProcessingData.Columns;
+      }
+      set {
+        //does nothing
+      }
+    }
+
+    public IEnumerable<string> ColumnNames {
+      get {
+        return PreProcessingData.VariableNames;
+      }
+      set {
+
+      }
+    }
+
+    public IEnumerable<string> RowNames {
+      get {
+        return Enumerable.Range(1, Rows).Select(n => n.ToString());
+      }
+      set {
+        throw new NotSupportedException();
+      }
+    }
+
+    public bool SortableView {
+      get {
+        return true;
+      }
+      set {
+        throw new NotSupportedException();
+      }
+    }
+
+    public bool ReadOnly {
+      get { return false; }
+    }
+
+
+    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) {
+
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new DataGridContent(this, cloner);
+    }
+
+    public void DeleteRows(IEnumerable<int> rows) {
+      PreProcessingData.DeleteRowsWithIndices(rows);
+    }
+
+    public void DeleteColumn(int column) {
+      PreProcessingData.DeleteColumn(column);
+    }
+
+    public bool Validate(string value, out string errorMessage, int columnIndex) {
+      return PreProcessingData.Validate(value, out errorMessage, columnIndex);
+    }
+
+    public string GetValue(int rowIndex, int columnIndex) {
+      return PreProcessingData.GetCellAsString(columnIndex, rowIndex);
+    }
+
+    public bool SetValue(string value, int rowIndex, int columnIndex) {
+      return PreProcessingData.SetValue(value, columnIndex, rowIndex);
+    }
+
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { PreProcessingData.Changed += value; }
+      remove { PreProcessingData.Changed -= value; }
+    }
+
+
+    #region unused stuff/not implemented but necessary due to IStringConvertibleMatrix
+#pragma warning disable 0067
+    // Is not used since DataGridContentView overrides dataGridView_CellValidating and uses 
+    // DataGridLogic#Validate(string value, out string errorMessage, int columnIndex)
+    public bool Validate(string value, out string errorMessage) {
+      errorMessage = string.Empty;
+      return true;
+    }
+
+    public event EventHandler ColumnsChanged;
+    public event EventHandler RowsChanged;
+    public event EventHandler ColumnNamesChanged;
+    public event EventHandler RowNamesChanged;
+    public event EventHandler SortableViewChanged;
+    public event EventHandler<EventArgs<int, int>> ItemChanged;
+    public event EventHandler Reset;
+
+#pragma warning restore 0067
+    #endregion
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/FilterContent.cs	(revision 13508)
@@ -0,0 +1,70 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.DataPreprocessing.Filter;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("Filter", "Represents the filter grid.")]
+  public class FilterContent : Item, IViewShortcut {
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Filter; }
+    }
+
+    private ICheckedItemCollection<IFilter> filters = new CheckedItemCollection<IFilter>();
+
+    public FilterLogic FilterLogic { get; private set; }
+
+    public ICheckedItemCollection<IFilter> Filters {
+      get {
+        return this.filters;
+      }
+      set {
+        this.filters = value;
+      }
+    }
+
+    private bool isAndCombination = true;
+    public bool IsAndCombination {
+      get {
+        return this.isAndCombination;
+      }
+      set {
+        this.isAndCombination = value;
+      }
+    }
+
+    public FilterContent(FilterLogic filterLogic) {
+      FilterLogic = filterLogic;
+    }
+
+    protected FilterContent(FilterContent content, Cloner cloner)
+      : base(content, cloner) {
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new FilterContent(this, cloner);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/HistogramContent.cs	(revision 13508)
@@ -0,0 +1,74 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("Histogram", "Represents the histogram grid.")]
+  public class HistogramContent : PreprocessingChartContent {
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Statistics; }
+    }
+    private const int MAX_DISTINCT_VALUES_FOR_CLASSIFCATION = 20;
+
+    private int classifierVariableIndex = 0;
+
+    public int ClassifierVariableIndex {
+      get { return this.classifierVariableIndex; }
+      set { this.classifierVariableIndex = value; }
+    }
+    public bool IsDetailedChartViewEnabled { get; set; }
+
+
+    public HistogramContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
+      AllInOneMode = false;
+    }
+
+    public HistogramContent(HistogramContent content, Cloner cloner)
+      : base(content, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new HistogramContent(this, cloner);
+    }
+
+    public IEnumerable<string> GetVariableNamesForHistogramClassification() {
+      List<string> doubleVariableNames = new List<string>();
+
+      //only return variable names from type double
+      for (int i = 0; i < PreprocessingData.Columns; ++i) {
+        if (PreprocessingData.VariableHasType<double>(i)) {
+          double distinctValueCount = PreprocessingData.GetValues<double>(i).GroupBy(x => x).Count();
+          bool distinctValuesOk = distinctValueCount <= MAX_DISTINCT_VALUES_FOR_CLASSIFCATION;
+          if (distinctValuesOk)
+            doubleVariableNames.Add(PreprocessingData.GetVariableName(i));
+        }
+      }
+      return doubleVariableNames;
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IDataGridContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IDataGridContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IDataGridContent.cs	(revision 13508)
@@ -0,0 +1,39 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.DataPreprocessing {
+  public interface IDataGridContent : IStringConvertibleMatrix {
+    ITransactionalPreprocessingData PreProcessingData { get; }
+    ManipulationLogic ManipulationLogic { get; }
+    FilterLogic FilterLogic { get; }
+
+    IDictionary<int, IList<int>> Selection { get; set; }
+
+    void DeleteRows(IEnumerable<int> rows);
+    void DeleteColumn(int column);
+    bool Validate(string value, out string errorMessage, int columnIndex);
+
+    event DataPreprocessingChangedEventHandler Changed;
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewChartShortcut.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewChartShortcut.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewChartShortcut.cs	(revision 13508)
@@ -0,0 +1,26 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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
+
+
+namespace HeuristicLab.DataPreprocessing {
+  public interface IViewChartShortcut : IViewShortcut {
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewShortcut.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewShortcut.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/IViewShortcut.cs	(revision 13508)
@@ -0,0 +1,27 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 {
+  public interface IViewShortcut : IItem {
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/LineChartContent.cs	(revision 13508)
@@ -0,0 +1,46 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+
+  [Item("LineChart", "Represents the line chart grid.")]
+  public class LineChartContent : PreprocessingChartContent {
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    public LineChartContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
+    }
+
+    public LineChartContent(LineChartContent content, Cloner cloner)
+      : base(content, cloner) {
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new LineChartContent(this, cloner);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ManipulationContent.cs	(revision 13508)
@@ -0,0 +1,57 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+
+  [Item("Manipulation", "Represents the available manipulations on a data set.")]
+  public class ManipulationContent : Item, IViewShortcut {
+
+    private ManipulationLogic manipulationLogic;
+    private SearchLogic searchLogic;
+    private FilterLogic filterLogic;
+
+    public ManipulationLogic ManipulationLogic { get { return manipulationLogic; } }
+    public SearchLogic SearchLogic { get { return searchLogic; } }
+    public FilterLogic FilterLogic { get { return filterLogic; } }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+
+    public ManipulationContent(ManipulationLogic theManipulationLogic, SearchLogic theSearchLogic, FilterLogic theFilterLogic) {
+      manipulationLogic = theManipulationLogic;
+      searchLogic = theSearchLogic;
+      filterLogic = theFilterLogic;
+    }
+
+    public ManipulationContent(ManipulationContent content, Cloner cloner) : base(content, cloner) { }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ManipulationContent(this, cloner);
+    }
+
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingChartContent.cs	(revision 13508)
@@ -0,0 +1,143 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("PreprocessingChart", "Represents a preprocessing chart.")]
+  public class PreprocessingChartContent : Item, IViewChartShortcut {
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.PieChart; }
+    }
+
+    private bool allInOneMode = true;
+    public bool AllInOneMode {
+      get { return this.allInOneMode; }
+      set { this.allInOneMode = value; }
+    }
+
+    private ICheckedItemList<StringValue> variableItemList = null;
+    public ICheckedItemList<StringValue> VariableItemList {
+      get { return this.variableItemList; }
+      set { this.variableItemList = value; }
+    }
+
+    public IFilteredPreprocessingData PreprocessingData { get; private set; }
+
+    public PreprocessingChartContent(IFilteredPreprocessingData preprocessingData) {
+      PreprocessingData = preprocessingData;
+    }
+
+    public PreprocessingChartContent(PreprocessingChartContent content, Cloner cloner)
+      : base(content, cloner) {
+      this.allInOneMode = content.allInOneMode;
+      this.PreprocessingData = content.PreprocessingData;
+      this.variableItemList = cloner.Clone<ICheckedItemList<StringValue>>(variableItemList);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PreprocessingChartContent(this, cloner);
+    }
+
+
+    public DataRow CreateDataRow(string variableName, DataRowVisualProperties.DataRowChartType chartType) {
+      IList<double> values = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableName));
+      DataRow row = new DataRow(variableName, "", values);
+      row.VisualProperties.ChartType = chartType;
+      return row;
+    }
+
+    public List<DataRow> CreateAllDataRows(DataRowVisualProperties.DataRowChartType chartType) {
+      List<DataRow> dataRows = new List<DataRow>();
+      foreach (var name in PreprocessingData.GetDoubleVariableNames())
+        dataRows.Add(CreateDataRow(name, chartType));
+      return dataRows;
+    }
+
+    public DataRow CreateSelectedDataRow(string variableName, DataRowVisualProperties.DataRowChartType chartType) {
+
+      IDictionary<int, IList<int>> selection = PreprocessingData.Selection;
+      int variableIndex = PreprocessingData.GetColumnIndex(variableName);
+
+      if (selection.Keys.Contains(variableIndex)) {
+        List<int> selectedIndices = new List<int>(selection[variableIndex]);
+        //need selection with more than 1 value
+        if (selectedIndices.Count < 2)
+          return null;
+
+        selectedIndices.Sort();
+        int start = selectedIndices[0];
+        int end = selectedIndices[selectedIndices.Count - 1];
+
+        DataRow rowSelect = CreateDataRowRange(variableName, start, end, chartType);
+        return rowSelect;
+      } else
+        return null;
+    }
+
+    public DataRow CreateDataRowRange(string variableName, int start, int end, DataRowVisualProperties.DataRowChartType chartType) {
+      IList<double> values = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableName));
+      IList<double> valuesRange = new List<double>();
+      for (int i = 0; i < values.Count; i++) {
+        if (i >= start && i <= end)
+          valuesRange.Add(values[i]);
+        else
+          valuesRange.Add(Double.NaN);
+      }
+
+      DataRow row = new DataRow(variableName, "", valuesRange);
+      row.VisualProperties.ChartType = chartType;
+      return row;
+    }
+
+    public List<DataRow> CreateAllSelectedDataRows(DataRowVisualProperties.DataRowChartType chartType) {
+      List<DataRow> dataRows = new List<DataRow>();
+      foreach (var name in PreprocessingData.GetDoubleVariableNames()) {
+        DataRow row = CreateSelectedDataRow(name, chartType);
+        if (row != null)
+          dataRows.Add(row);
+      }
+      return dataRows;
+    }
+
+
+    public ICheckedItemList<StringValue> CreateVariableItemList(IEnumerable<string> checkedItems = null) {
+      ICheckedItemList<StringValue> itemList = new CheckedItemList<StringValue>();
+      foreach (string name in PreprocessingData.GetDoubleVariableNames()) {
+        var n = new StringValue(name);
+        itemList.Add(n, (checkedItems == null) ? true : checkedItems.Contains(name));
+      }
+      return new ReadOnlyCheckedItemList<StringValue>(itemList);
+    }
+
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { PreprocessingData.Changed += value; }
+      remove { PreprocessingData.Changed -= value; }
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingDataTable.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingDataTable.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/PreprocessingDataTable.cs	(revision 13508)
@@ -0,0 +1,58 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("PreprossingDataTable", "A table of data values.")]
+  public class PreprocessingDataTable : DataTable {
+
+    public PreprocessingDataTable()
+      : base() {
+      SelectedRows = new NamedItemCollection<DataRow>();
+    }
+    public PreprocessingDataTable(string name)
+      : base(name) {
+      SelectedRows = new NamedItemCollection<DataRow>();
+    }
+
+    protected PreprocessingDataTable(PreprocessingDataTable original, Cloner cloner)
+      : base(original, cloner) {
+      this.selectedRows = cloner.Clone(original.selectedRows);
+    }
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new PreprocessingDataTable(this, cloner);
+    }
+
+    private NamedItemCollection<DataRow> selectedRows;
+    public NamedItemCollection<DataRow> SelectedRows {
+      get { return selectedRows; }
+      private set {
+        if (selectedRows != null) throw new InvalidOperationException("Rows already set");
+        selectedRows = value;
+      }
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/ScatterPlotContent.cs	(revision 13508)
@@ -0,0 +1,93 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
+ *
+ * This file is part of HeuristicLab.
+ *
+ * HeuristicLab is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * HeuristicLab is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
+ */
+#endregion
+
+using System.Collections.Generic;
+using System.Drawing;
+using System.Linq;
+using HeuristicLab.Analysis;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+
+  [Item("ScatterPlot", "Represents a scatter plot.")]
+  public class ScatterPlotContent : PreprocessingChartContent {
+
+    public string SelectedXVariable { get; set; }
+    public string SelectedYVariable { get; set; }
+    public string SelectedColorVariable { get; set; }
+
+    public ScatterPlotContent(IFilteredPreprocessingData preprocessingData)
+      : base(preprocessingData) {
+    }
+
+    public ScatterPlotContent(ScatterPlotContent content, Cloner cloner)
+      : base(content, cloner) {
+      this.SelectedXVariable = content.SelectedXVariable;
+      this.SelectedYVariable = content.SelectedYVariable;
+      this.SelectedColorVariable = content.SelectedColorVariable;
+    }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Performance; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new ScatterPlotContent(this, cloner);
+    }
+
+    public ScatterPlot CreateScatterPlot(string variableNameX, string variableNameY, string variableNameColor = "-") {
+      ScatterPlot scatterPlot = new ScatterPlot();
+
+      IList<double> xValues = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableNameX));
+      IList<double> yValues = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableNameY));
+      if (variableNameColor == null || variableNameColor == "-") {
+        List<Point2D<double>> points = new List<Point2D<double>>();
+
+        for (int i = 0; i < xValues.Count; i++) {
+          Point2D<double> point = new Point2D<double>(xValues[i], yValues[i]);
+          points.Add(point);
+        }
+
+        ScatterPlotDataRow scdr = new ScatterPlotDataRow(variableNameX + " - " + variableNameY, "", points);
+        scatterPlot.Rows.Add(scdr);
+
+      } else {
+        var colorValues = PreprocessingData.GetValues<double>(PreprocessingData.GetColumnIndex(variableNameColor));
+        var data = xValues.Zip(yValues, (x, y) => new { x, y }).Zip(colorValues, (v, c) => new { v.x, v.y, c }).ToList();
+        var gradients = ColorGradient.Colors;
+        int curGradient = 0;
+        int numColors = colorValues.Distinct().Count();
+        foreach (var colorValue in colorValues.Distinct()) {
+          var values = data.Where(x => x.c == colorValue);
+          var row = new ScatterPlotDataRow(
+            variableNameX + " - " + variableNameY + " (" + colorValue + ")",
+            "",
+            values.Select(v => new Point2D<double>(v.x, v.y)),
+            new ScatterPlotDataRowVisualProperties() { Color = gradients[curGradient] });
+          curGradient += gradients.Count / numColors;
+          scatterPlot.Rows.Add(row);
+        }
+      }
+      return scatterPlot;
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/StatisticsContent.cs	(revision 13508)
@@ -0,0 +1,58 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("Statistics", "Represents the statistics grid.")]
+  public class StatisticsContent : Item, IViewShortcut {
+
+    private readonly StatisticsLogic statisticsLogic;
+    public StatisticsContent(StatisticsLogic theStatisticsLogic) {
+      statisticsLogic = theStatisticsLogic;
+    }
+
+    public StatisticsContent(StatisticsContent content, Cloner cloner)
+      : base(content, cloner) {
+
+    }
+
+    public StatisticsLogic StatisticsLogic {
+      get { return statisticsLogic; }
+    }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Object; }
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new StatisticsContent(this, cloner);
+    }
+
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { statisticsLogic.Changed += value; }
+      remove { statisticsLogic.Changed -= value; }
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Content/TransformationContent.cs	(revision 13508)
@@ -0,0 +1,56 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Drawing;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DataPreprocessing {
+  [Item("Transformation", "Represents the transformation grid.")]
+  public class TransformationContent : Item, IViewShortcut {
+
+    public IPreprocessingData Data { get; private set; }
+    public FilterLogic FilterLogic { get; private set; }
+
+    public ICheckedItemList<ITransformation> CheckedTransformationList { get; private set; }
+
+    public static new Image StaticItemImage {
+      get { return HeuristicLab.Common.Resources.VSImageLibrary.Method; }
+    }
+
+    public TransformationContent(IPreprocessingData data, FilterLogic filterLogic) {
+      Data = data;
+      CheckedTransformationList = new CheckedItemList<ITransformation>();
+      FilterLogic = filterLogic;
+    }
+
+    public TransformationContent(TransformationContent original, Cloner cloner)
+      : base(original, cloner) {
+      Data = original.Data;
+      CheckedTransformationList = new CheckedItemList<ITransformation>(original.CheckedTransformationList);
+    }
+
+    public override IDeepCloneable Clone(Cloner cloner) {
+      return new TransformationContent(this, cloner);
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/DataPreprocessingChangedEvent.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/DataPreprocessingChangedEvent.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/DataPreprocessingChangedEvent.cs	(revision 13508)
@@ -0,0 +1,49 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 enum DataPreprocessingChangedEventType {
+    DeleteColumn,
+    AddColumn,
+    ChangeColumn,
+    DeleteRow,
+    AddRow,
+    ChangeItem,
+    Any,
+    Transformation
+  }
+
+  public class DataPreprocessingChangedEventArgs : EventArgs {
+    public DataPreprocessingChangedEventType Type { get; private set; }
+    public int Row { get; private set; }
+    public int Column { get; private set; }
+
+    public DataPreprocessingChangedEventArgs(DataPreprocessingChangedEventType type, int column, int row) {
+      Type = type;
+      Column = column;
+      Row = row;
+    }
+  }
+
+  public delegate void DataPreprocessingChangedEventHandler(object sender, DataPreprocessingChangedEventArgs e);
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/FilteredPreprocessingData.cs	(revision 13508)
@@ -0,0 +1,278 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using HeuristicLab.Common;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DataPreprocessing {
+  public class FilteredPreprocessingData : NamedItem, IFilteredPreprocessingData {
+    private readonly ITransactionalPreprocessingData originalData;
+    private ITransactionalPreprocessingData filteredData;
+
+    public IntRange TrainingPartition {
+      get { return originalData.TrainingPartition; }
+    }
+
+    public IntRange TestPartition {
+      get { return originalData.TestPartition; }
+    }
+
+    public IList<ITransformation> Transformations {
+      get { return originalData.Transformations; }
+    }
+
+    public IEnumerable<string> VariableNames {
+      get { return ActiveData.VariableNames; }
+    }
+
+    public IDictionary<int, IList<int>> Selection {
+      get { return originalData.Selection; }
+      set { originalData.Selection = value; }
+    }
+
+    public int Columns {
+      get { return ActiveData.Columns; }
+    }
+
+    public int Rows {
+      get { return ActiveData.Rows; }
+    }
+
+    public ITransactionalPreprocessingData ActiveData {
+      get { return IsFiltered ? filteredData : originalData; }
+    }
+
+    public bool IsUndoAvailable {
+      get { return IsFiltered ? false : originalData.IsUndoAvailable; }
+    }
+
+    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();
+      filteredData.InTransaction(() => {
+        for (int row = (rowFilters.Length - 1); row >= 0; --row) {
+          if (rowFilters[row]) {
+            filteredData.DeleteRow(row);
+          }
+        }
+      });
+      OnFilterChanged();
+    }
+
+    public void PersistFilter() {
+      originalData.InTransaction(() => {
+        for (int i = 0; i < filteredData.Columns; ++i) {
+          if (filteredData.VariableHasType<double>(i)) {
+            originalData.SetValues<double>(i, filteredData.GetValues<double>(i));
+          } else if (filteredData.VariableHasType<string>(i)) {
+            originalData.SetValues<string>(i, filteredData.GetValues<string>(i));
+          } else if (filteredData.VariableHasType<DateTime>(i)) {
+            originalData.SetValues<DateTime>(i, filteredData.GetValues<DateTime>(i));
+          } else {
+            throw new ArgumentException("Data types of columns do not match");
+          }
+        }
+      });
+      ResetFilter();
+    }
+
+    public void ResetFilter() {
+      filteredData = null;
+      OnFilterChanged();
+    }
+
+    private void OnFilterChanged() {
+      if (FilterChanged != null) {
+        FilterChanged(this, new EventArgs());
+      }
+    }
+
+    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: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IFilteredPreprocessingData.cs	(revision 13508)
@@ -0,0 +1,33 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 IFilteredPreprocessingData : ITransactionalPreprocessingData {
+    void SetFilter(bool[] rowFilters);
+    void PersistFilter();
+    void ResetFilter();
+    bool IsFiltered { get; }
+
+    event EventHandler FilterChanged;
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/IPreprocessingData.cs	(revision 13508)
@@ -0,0 +1,77 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using HeuristicLab.Core;
+using HeuristicLab.Data;
+using HeuristicLab.Problems.DataAnalysis;
+
+namespace HeuristicLab.DataPreprocessing {
+
+  public interface IPreprocessingData : INamedItem {
+    T GetCell<T>(int columnIndex, int rowIndex);
+
+    void SetCell<T>(int columnIndex, int rowIndex, T value);
+
+    string GetCellAsString(int columnIndex, int rowIndex);
+
+    IList<T> GetValues<T>(int columnIndex, bool considerSelection = false);
+
+    void SetValues<T>(int columnIndex, IList<T> values);
+    bool SetValue(string value, int columnIndex, int rowIndex);
+
+    void InsertRow(int rowIndex);
+    void DeleteRow(int rowIndex);
+    void DeleteRowsWithIndices(IEnumerable<int> rows);
+    void InsertColumn<T>(string variableName, int columnIndex);
+
+    void DeleteColumn(int columnIndex);
+
+    void RenameColumn(int columnIndex, string name);
+    void RenameColumns(IList<string> names);
+
+    bool AreAllStringColumns(IEnumerable<int> columnIndices);
+    bool Validate(string value, out string errorMessage, int columnIndex);
+
+    IntRange TrainingPartition { get; }
+    IntRange TestPartition { get; }
+
+    IList<ITransformation> Transformations { get; }
+
+    IEnumerable<string> VariableNames { get; }
+    IEnumerable<string> GetDoubleVariableNames();
+    string GetVariableName(int columnIndex);
+    int GetColumnIndex(string variableName);
+
+    bool VariableHasType<T>(int columnIndex);
+
+    int Columns { get; }
+    int Rows { get; }
+
+    Dataset ExportToDataset();
+
+    IDictionary<int, IList<int>> Selection { get; set; }
+    void ClearSelection();
+
+    event EventHandler SelectionChanged;
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/ITransactionalPreprocessingData.cs	(revision 13508)
@@ -0,0 +1,35 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/PreprocessingData.cs	(revision 13508)
@@ -0,0 +1,211 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.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 abstract class PreprocessingData : NamedItem, IPreprocessingData {
+
+    public IntRange TrainingPartition { get; set; }
+    public IntRange TestPartition { get; set; }
+
+    protected IList<ITransformation> transformations;
+    public IList<ITransformation> Transformations {
+      get { return transformations; }
+    }
+
+    protected IList<IList> variableValues;
+    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 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();
+      }
+    }
+
+    protected PreprocessingData(PreprocessingData original, Cloner cloner)
+      : base(original, cloner) {
+      variableValues = CopyVariableValues(original.variableValues);
+      variableNames = new List<string>(original.variableNames);
+      TrainingPartition = (IntRange)original.TrainingPartition.Clone(cloner);
+      TestPartition = (IntRange)original.TestPartition.Clone(cloner);
+      transformations = new List<ITransformation>();
+
+      RegisterEventHandler();
+    }
+
+    protected PreprocessingData(IDataAnalysisProblemData problemData)
+      : base() {
+      Name = "Preprocessing Data";
+
+      transformations = new List<ITransformation>();
+      selection = new Dictionary<int, IList<int>>();
+
+      Import(problemData);
+
+      RegisterEventHandler();
+    }
+
+    public void Import(IDataAnalysisProblemData problemData) {
+      Dataset dataset = (Dataset)problemData.Dataset;
+      variableNames = new List<string>(problemData.Dataset.VariableNames);
+
+      int columnIndex = 0;
+      variableValues = new List<IList>();
+      foreach (var variableName in problemData.Dataset.VariableNames) {
+        if (dataset.VariableHasType<double>(variableName)) {
+          variableValues.Insert(columnIndex, dataset.GetDoubleValues(variableName).ToList());
+        } else if (dataset.VariableHasType<string>(variableName)) {
+          variableValues.Insert(columnIndex, dataset.GetStringValues(variableName).ToList());
+        } else if (dataset.VariableHasType<DateTime>(variableName)) {
+          variableValues.Insert(columnIndex, dataset.GetDateTimeValues(variableName).ToList());
+        } else {
+          throw new ArgumentException("The datatype of column " + variableName + " must be of type double, string or DateTime");
+        }
+        ++columnIndex;
+      }
+
+      TrainingPartition = new IntRange(problemData.TrainingPartition.Start, problemData.TrainingPartition.End);
+      TestPartition = new IntRange(problemData.TestPartition.Start, problemData.TestPartition.End);
+    }
+
+    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 - 1);
+      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 event DataPreprocessingChangedEventHandler Changed;
+    protected virtual void OnChanged(DataPreprocessingChangedEventType type, int column, int row) {
+      var listeners = Changed;
+      if (listeners != null) listeners(this, new DataPreprocessingChangedEventArgs(type, column, row));
+    }
+    #endregion
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Data/TransactionalPreprocessingData.cs	(revision 13508)
@@ -0,0 +1,361 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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 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 (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, -1);
+      ResetPartitions();
+    }
+
+    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 (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+      ResetPartitions();
+    }
+
+    public override void DeleteRow(int rowIndex) {
+      SaveSnapshot(DataPreprocessingChangedEventType.AddRow, -1, rowIndex);
+      foreach (IList column in variableValues) {
+        column.RemoveAt(rowIndex);
+      }
+      if (!IsInTransaction)
+        OnChanged(DataPreprocessingChangedEventType.DeleteRow, -1, rowIndex);
+      ResetPartitions();
+    }
+
+    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);
+    }
+
+
+    private void ResetPartitions() {
+      TrainingPartition = new IntRange();
+      TestPartition = new IntRange();
+    }
+
+    #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: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/HeuristicLab.DataPreprocessing-3.4.csproj	(revision 13508)
@@ -78,42 +78,36 @@
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="Implementations\ScatterPlotContent.cs" />
-    <Compile Include="Implementations\DataCompletenessChartContent.cs" />
-    <Compile Include="Implementations\FilteredPreprocessingData.cs" />
-    <Compile Include="Implementations\ManipulationContent.cs" />
-    <Compile Include="Implementations\PreprocessingChartContent.cs" />
-    <Compile Include="Implementations\PreprocessingData.cs" />
-    <Compile Include="Implementations\PreprocessingDataTable.cs" />
-    <Compile Include="Interfaces\IViewChartShortcut.cs" />
-    <Compile Include="Interfaces\IFilteredPreprocessingData.cs" />
-    <Compile Include="Implementations\CorrelationMatrixContent.cs" />
+    <Compile Include="Content\ScatterPlotContent.cs" />
+    <Compile Include="Content\DataCompletenessChartContent.cs" />
+    <Compile Include="Data\FilteredPreprocessingData.cs" />
+    <Compile Include="Content\ManipulationContent.cs" />
+    <Compile Include="Content\PreprocessingChartContent.cs" />
+    <Compile Include="Data\PreprocessingData.cs" />
+    <Compile Include="Content\PreprocessingDataTable.cs" />
+    <Compile Include="Content\IViewChartShortcut.cs" />
+    <Compile Include="Data\IFilteredPreprocessingData.cs" />
+    <Compile Include="Content\CorrelationMatrixContent.cs" />
     <Compile Include="PreprocessingTransformator.cs" />
-    <Compile Include="Utils\DataPreprocessingChangedEvent.cs" />
-    <Compile Include="Implementations\Filter\ComparisonFilter.cs" />
-    <Compile Include="Implementations\Filter\IFilter.cs" />
-    <Compile Include="Implementations\ManipulationLogic.cs" />
-    <Compile Include="Interfaces\IPreprocessingData.cs" />
-    <Compile Include="Interfaces\IDataGridLogic.cs" />
-    <Compile Include="Implementations\FilterContent.cs" />
-    <Compile Include="Implementations\FilterLogic.cs" />
-    <Compile Include="Implementations\HistogramContent.cs" />
-    <Compile Include="Implementations\LineChartContent.cs" />
-    <Compile Include="Implementations\StatisticsContent.cs" />
-    <Compile Include="Implementations\TransformationContent.cs" />
-    <Compile Include="Interfaces\IFilterLogic.cs" />
-    <Compile Include="Interfaces\IManipulationLogic.cs" />
-    <Compile Include="Interfaces\ITransformationLogic.cs" />
-    <Compile Include="Interfaces\IViewShortcut.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="Data\IPreprocessingData.cs" />
+    <Compile Include="Content\FilterContent.cs" />
+    <Compile Include="Logic\FilterLogic.cs" />
+    <Compile Include="Content\HistogramContent.cs" />
+    <Compile Include="Content\LineChartContent.cs" />
+    <Compile Include="Content\StatisticsContent.cs" />
+    <Compile Include="Content\TransformationContent.cs" />
+    <Compile Include="Content\IViewShortcut.cs" />
     <Compile Include="ProblemDataCreator.cs" />
     <None Include="Plugin.cs.frame" />
-    <Compile Include="Implementations\DataGridContent.cs" />
+    <Compile Include="Content\DataGridContent.cs" />
     <Compile Include="PreprocessingContext.cs" />
-    <Compile Include="Implementations\TransactionalPreprocessingData.cs" />
-    <Compile Include="Implementations\SearchLogic.cs" />
-    <Compile Include="Implementations\StatisticsLogic.cs" />
-    <Compile Include="Interfaces\IDataGridContent.cs" />
-    <Compile Include="Interfaces\ISearchLogic.cs" />
-    <Compile Include="Interfaces\IStatisticsLogic.cs" />
-    <Compile Include="Interfaces\ITransactionalPreprocessingData.cs" />
+    <Compile Include="Data\TransactionalPreprocessingData.cs" />
+    <Compile Include="Logic\SearchLogic.cs" />
+    <Compile Include="Logic\StatisticsLogic.cs" />
+    <Compile Include="Content\IDataGridContent.cs" />
+    <Compile Include="Data\ITransactionalPreprocessingData.cs" />
     <Compile Include="Plugin.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
@@ -162,4 +156,5 @@
       <Project>{102BC7D3-0EF9-439C-8F6D-96FF0FDB8E1B}</Project>
       <Name>HeuristicLab.Persistence-3.3</Name>
+      <Private>False</Private>
     </ProjectReference>
     <ProjectReference Include="..\..\HeuristicLab.PluginInfrastructure\3.3\HeuristicLab.PluginInfrastructure-3.3.csproj">
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/ComparisonFilter.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/ComparisonFilter.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/ComparisonFilter.cs	(revision 13508)
@@ -0,0 +1,140 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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();
+        }
+      }
+    }
+
+    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: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/IFilter.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/IFilter.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/Filter/IFilter.cs	(revision 13508)
@@ -0,0 +1,29 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/FilterLogic.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/FilterLogic.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/FilterLogic.cs	(revision 13508)
@@ -0,0 +1,96 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using System.Linq;
+using HeuristicLab.DataPreprocessing.Filter;
+
+namespace HeuristicLab.DataPreprocessing {
+  public class FilterLogic {
+
+    public IFilteredPreprocessingData PreprocessingData { get; private set; }
+
+    public bool IsFiltered {
+      get {
+        return PreprocessingData.IsFiltered;
+      }
+    }
+
+    public FilterLogic(IFilteredPreprocessingData preprocessingData) {
+      PreprocessingData = preprocessingData;
+    }
+
+    public bool[] GetFilterResult(IList<IFilter> filters, bool isAndCombination) {
+      IList<IFilter> activeFilters = filters.Where(f => f.Active && f.ConstraintData != null).ToList<IFilter>();
+
+      if (activeFilters.Count == 0) {
+        return CreateBoolArray(PreprocessingData.Rows, false);
+      }
+      return GetActiveFilterResult(activeFilters, isAndCombination);
+    }
+
+    private bool[] GetActiveFilterResult(IList<IFilter> activeFilters, bool isAndCombination) {
+      bool[] result = CreateBoolArray(PreprocessingData.Rows, !isAndCombination);
+
+      foreach (IFilter filter in activeFilters) {
+        bool[] filterResult = filter.Check();
+        for (int row = 0; row < result.Length; ++row) {
+          result[row] = Result(result[row], filterResult[row], isAndCombination);
+        }
+      }
+      return result;
+    }
+
+    public bool[] Preview(IList<IFilter> filters, bool isAndCombination) {
+      IList<IFilter> activeFilters = filters.Where(f => f.Active && f.ConstraintData != null).ToList<IFilter>();
+      if (activeFilters.Count > 0) {
+        var result = GetActiveFilterResult(activeFilters, isAndCombination);
+        PreprocessingData.SetFilter(result);
+        return result;
+      } else {
+        return CreateBoolArray(PreprocessingData.Rows, false);
+      }
+    }
+
+    public bool[] CreateBoolArray(int rows, bool value) {
+      return Enumerable.Repeat<bool>(value, rows).ToArray();
+    }
+
+    public bool Result(bool current, bool addition, bool isAndCombination) {
+      return isAndCombination ? current || addition : current && addition;
+    }
+
+    public void Apply(IList<IFilter> filters, bool isAndCombination) {
+      PreprocessingData.PersistFilter();
+      Reset();
+    }
+
+    public void Reset() {
+      PreprocessingData.ResetFilter();
+    }
+
+    public event EventHandler FilterChanged {
+      add { PreprocessingData.FilterChanged += value; }
+      remove { PreprocessingData.FilterChanged -= value; }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/ManipulationLogic.cs	(revision 13508)
@@ -0,0 +1,405 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using System.Linq;
+using HeuristicLab.Data;
+
+namespace HeuristicLab.DataPreprocessing {
+  public class ManipulationLogic {
+    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly StatisticsLogic statisticsLogic;
+    private readonly SearchLogic searchLogic;
+
+    public IEnumerable<string> VariableNames {
+      get { return preprocessingData.VariableNames; }
+    }
+
+    public ITransactionalPreprocessingData PreProcessingData {
+      get { return preprocessingData; }
+    }
+
+    public ManipulationLogic(ITransactionalPreprocessingData _prepocessingData, SearchLogic theSearchLogic, StatisticsLogic theStatisticsLogic) {
+      preprocessingData = _prepocessingData;
+      searchLogic = theSearchLogic;
+      statisticsLogic = theStatisticsLogic;
+    }
+
+    public void ReplaceIndicesByValue<T>(int columnIndex, IEnumerable<int> rowIndices, T value) {
+      foreach (int index in rowIndices) {
+        preprocessingData.SetCell<T>(columnIndex, index, value);
+      }
+    }
+
+    public void ReplaceIndicesByAverageValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      preprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          if (preprocessingData.VariableHasType<double>(column.Key)) {
+            double average = statisticsLogic.GetAverage(column.Key, considerSelection);
+            ReplaceIndicesByValue<double>(column.Key, column.Value, average);
+          } else if (preprocessingData.VariableHasType<DateTime>(column.Key)) {
+            DateTime average = statisticsLogic.GetAverageDateTime(column.Key, considerSelection);
+            ReplaceIndicesByValue<DateTime>(column.Key, column.Value, average);
+          }
+        }
+      });
+    }
+
+    public void ReplaceIndicesByMedianValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      preprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          if (preprocessingData.VariableHasType<double>(column.Key)) {
+            double median = statisticsLogic.GetMedian(column.Key, considerSelection);
+            ReplaceIndicesByValue<double>(column.Key, column.Value, median);
+          } else if (preprocessingData.VariableHasType<DateTime>(column.Key)) {
+            DateTime median = statisticsLogic.GetMedianDateTime(column.Key, considerSelection);
+            ReplaceIndicesByValue<DateTime>(column.Key, column.Value, median);
+          }
+        }
+      });
+    }
+
+    public void ReplaceIndicesByRandomValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      preprocessingData.InTransaction(() => {
+        Random r = new Random();
+
+        foreach (var column in cells) {
+          if (preprocessingData.VariableHasType<double>(column.Key)) {
+            double max = statisticsLogic.GetMax<double>(column.Key, considerSelection);
+            double min = statisticsLogic.GetMin<double>(column.Key, considerSelection);
+            double randMultiplier = (max - min);
+            foreach (int index in column.Value) {
+              double rand = r.NextDouble() * randMultiplier + min;
+              preprocessingData.SetCell<double>(column.Key, index, rand);
+            }
+          } else if (preprocessingData.VariableHasType<DateTime>(column.Key)) {
+            DateTime min = statisticsLogic.GetMin<DateTime>(column.Key, considerSelection);
+            DateTime max = statisticsLogic.GetMax<DateTime>(column.Key, considerSelection);
+            double randMultiplier = (max - min).TotalSeconds;
+            foreach (int index in column.Value) {
+              double rand = r.NextDouble() * randMultiplier;
+              preprocessingData.SetCell<DateTime>(column.Key, index, min.AddSeconds(rand));
+            }
+          }
+        }
+      });
+    }
+
+    public void ReplaceIndicesByLinearInterpolationOfNeighbours(IDictionary<int, IList<int>> cells) {
+      preprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          int countValues = 0;
+          if (preprocessingData.VariableHasType<double>(column.Key)) {
+            countValues = preprocessingData.GetValues<double>(column.Key).Count();
+          } else if (preprocessingData.VariableHasType<DateTime>(column.Key)) {
+            countValues = preprocessingData.GetValues<DateTime>(column.Key).Count();
+          }
+
+          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) {
+      List<Tuple<int, int>> startEndings = new List<Tuple<int, int>>();
+      var rowIndices = column.Value;
+      rowIndices = rowIndices.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;
+    }
+
+    public void ReplaceIndicesBySmoothing(IDictionary<int, IList<int>> cells) {
+      preprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          int countValues = preprocessingData.Rows;
+
+          foreach (int index in column.Value) {
+            // dont replace first or last values
+            if (index > 0 && index < countValues) {
+              int prevIndex = indexOfPrevPresentValue(column.Key, index);
+              int nextIndex = indexOfNextPresentValue(column.Key, index);
+
+              // no neighbours found
+              if (prevIndex < 0 || nextIndex >= countValues) {
+                continue;
+              }
+
+              Interpolate(column, prevIndex, nextIndex);
+            }
+          }
+        }
+      });
+    }
+
+    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 && searchLogic.IsMissingValue(columnIndex, offset)) {
+        offset--;
+      }
+
+      return offset;
+    }
+
+    private int indexOfNextPresentValue(int columnIndex, int start) {
+      int offset = start + 1;
+      while (offset < preprocessingData.Rows && searchLogic.IsMissingValue(columnIndex, offset)) {
+        offset++;
+      }
+
+      return offset;
+    }
+
+    public void ReplaceIndicesByMostCommonValue(IDictionary<int, IList<int>> cells, bool considerSelection = false) {
+      preprocessingData.InTransaction(() => {
+        foreach (var column in cells) {
+          if (preprocessingData.VariableHasType<double>(column.Key)) {
+            ReplaceIndicesByValue<double>(column.Key, column.Value, statisticsLogic.GetMostCommonValue<double>(column.Key, considerSelection));
+          } else if (preprocessingData.VariableHasType<string>(column.Key)) {
+            ReplaceIndicesByValue<string>(column.Key, column.Value, statisticsLogic.GetMostCommonValue<string>(column.Key, considerSelection));
+          } else if (preprocessingData.VariableHasType<DateTime>(column.Key)) {
+            ReplaceIndicesByValue<DateTime>(column.Key, column.Value, statisticsLogic.GetMostCommonValue<DateTime>(column.Key, considerSelection));
+          } else {
+            throw new ArgumentException("column with index: " + column.Key + " contains a non supported type.");
+          }
+        }
+      });
+    }
+
+    public void Shuffle(bool shuffleRangesSeparately) {
+      Random random = new Random();
+      var ranges = new[] { preprocessingData.TestPartition, preprocessingData.TrainingPartition };
+      if (shuffleRangesSeparately) {
+        preprocessingData.InTransaction(() => {
+          // process all given ranges - e.g. TrainingPartition, TestPartition
+          foreach (IntRange range in ranges) {
+            List<Tuple<int, int>> shuffledIndices = new List<Tuple<int, int>>();
+
+            // generate random indices used for shuffeling each column
+            for (int i = range.End - 1; i >= range.Start; --i) {
+              int rand = random.Next(range.Start, i);
+              shuffledIndices.Add(new Tuple<int, int>(i, rand));
+            }
+
+            ShuffleToIndices(shuffledIndices);
+          }
+        });
+      } else {
+        preprocessingData.InTransaction(() => {
+          var indices = ranges.SelectMany(x => Enumerable.Range(x.Start, x.Size)).ToList();
+          var shuffledIndices = indices.OrderBy(x => random.Next());
+          ShuffleToIndices(indices.Zip(shuffledIndices, (i, j) => new Tuple<int, int>(i, j)).ToList());
+        });
+      }
+    }
+
+    public void ReOrderToIndices(IEnumerable<int> indices) {
+      List<Tuple<int, int>> indicesTuple = new List<Tuple<int, int>>();
+
+      for (int i = 0; i < indices.Count(); ++i) {
+        indicesTuple.Add(new Tuple<int, int>(i, indices.ElementAt(i)));
+      }
+
+      ReOrderToIndices(indicesTuple);
+    }
+
+    public void ReOrderToIndices(IList<System.Tuple<int, 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);
+          }
+        }
+      });
+    }
+
+    public void ShuffleToIndices(IList<System.Tuple<int, int>> indices) {
+      preprocessingData.InTransaction(() => {
+        for (int i = 0; i < preprocessingData.Columns; ++i) {
+          if (preprocessingData.VariableHasType<double>(i)) {
+            ShuffleToIndices<double>(i, indices);
+          } else if (preprocessingData.VariableHasType<string>(i)) {
+            ShuffleToIndices<string>(i, indices);
+          } else if (preprocessingData.VariableHasType<DateTime>(i)) {
+            ShuffleToIndices<DateTime>(i, indices);
+          }
+        }
+      });
+    }
+
+    private void reOrderToIndices<T>(int columnIndex, IList<Tuple<int, int>> indices) {
+
+      List<T> originalData = new List<T>(preprocessingData.GetValues<T>(columnIndex));
+
+      // process all columns equally
+      foreach (Tuple<int, int> index in indices) {
+        int originalIndex = index.Item1;
+        int replaceIndex = index.Item2;
+
+        T replaceValue = originalData.ElementAt<T>(replaceIndex);
+        preprocessingData.SetCell<T>(columnIndex, originalIndex, replaceValue);
+      }
+    }
+
+    private void ShuffleToIndices<T>(int columnIndex, IList<Tuple<int, int>> indices) {
+      // process all columns equally
+      foreach (Tuple<int, int> index in indices) {
+        int originalIndex = index.Item1;
+        int replaceIndex = index.Item2;
+
+        T tmp = preprocessingData.GetCell<T>(columnIndex, originalIndex);
+        T replaceValue = preprocessingData.GetCell<T>(columnIndex, replaceIndex);
+
+        preprocessingData.SetCell<T>(columnIndex, originalIndex, replaceValue);
+        preprocessingData.SetCell<T>(columnIndex, replaceIndex, tmp);
+      }
+    }
+
+    public void ReplaceIndicesByValue(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 List<int> RowsWithMissingValuesGreater(double percent) {
+
+      List<int> rows = new List<int>();
+
+      for (int i = 0; i < preprocessingData.Rows; ++i) {
+        int missingCount = statisticsLogic.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 = statisticsLogic.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) || preprocessingData.VariableHasType<DateTime>(i)) {
+          double columnVariance = statisticsLogic.GetVariance(i);
+          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) {
+      rows.Sort();
+      rows.Reverse();
+      preprocessingData.InTransaction(() => {
+        foreach (int row in rows) {
+          preprocessingData.DeleteRow(row);
+        }
+      });
+    }
+
+    private void DeleteColumns(List<int> columns) {
+      columns.Sort();
+      columns.Reverse();
+      preprocessingData.InTransaction(() => {
+        foreach (int column in columns) {
+          preprocessingData.DeleteColumn(column);
+        }
+      });
+    }
+
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/SearchLogic.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/SearchLogic.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/SearchLogic.cs	(revision 13508)
@@ -0,0 +1,161 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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;
+
+namespace HeuristicLab.DataPreprocessing {
+  public class SearchLogic {
+    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly FilterLogic filterLogic;
+
+    private Dictionary<int, IList<int>> MissingValueIndicies { get; set; }
+    private Dictionary<int, IList> ValuesWithoutNaN { get; set; }
+
+    public IEnumerable<string> VariableNames {
+      get { return preprocessingData.VariableNames; }
+    }
+
+    public int Columns {
+      get { return preprocessingData.Columns; }
+    }
+
+    public int Rows {
+      get { return preprocessingData.Rows; }
+    }
+
+    public SearchLogic(ITransactionalPreprocessingData thePreprocessingData, FilterLogic theFilterLogic) {
+      preprocessingData = thePreprocessingData;
+      filterLogic = theFilterLogic;
+
+      MissingValueIndicies = new Dictionary<int, IList<int>>();
+      ValuesWithoutNaN = new Dictionary<int, IList>();
+
+      preprocessingData.Changed += PreprocessingData_Changed;
+      filterLogic.FilterChanged += FilterLogic_FilterChanged;
+    }
+
+    void FilterLogic_FilterChanged(object sender, EventArgs e) {
+      //recalculate
+      for (int i = 0; i < Columns; i++) {
+        MissingValueIndicies.Remove(i);
+        ValuesWithoutNaN.Remove(i);
+      }
+    }
+
+    void PreprocessingData_Changed(object sender, DataPreprocessingChangedEventArgs e) {
+      switch (e.Type) {
+        case DataPreprocessingChangedEventType.DeleteColumn:
+        case DataPreprocessingChangedEventType.ChangeColumn:
+          MissingValueIndicies.Remove(e.Column);
+          ValuesWithoutNaN.Remove(e.Column);
+          break;
+        case DataPreprocessingChangedEventType.AddColumn:
+          //cache does not need to be updated, will be calculated the first time it is requested
+          break;
+        case DataPreprocessingChangedEventType.DeleteRow:
+        case DataPreprocessingChangedEventType.AddRow:
+        case DataPreprocessingChangedEventType.ChangeItem:
+        case DataPreprocessingChangedEventType.Any:
+        case DataPreprocessingChangedEventType.Transformation:
+        default:
+          MissingValueIndicies = new Dictionary<int, IList<int>>();
+          ValuesWithoutNaN = new Dictionary<int, IList>();
+          break;
+      }
+    }
+
+    public IDictionary<int, IList<int>> GetMissingValueIndices() {
+      var dic = new Dictionary<int, IList<int>>();
+      for (int i = 0; i < preprocessingData.Columns; ++i) {
+        dic.Add(i, GetMissingValueIndices(i));
+      }
+      return dic;
+    }
+
+    public bool IsMissingValue(int columnIndex, int rowIndex) {
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        return double.IsNaN(preprocessingData.GetCell<double>(columnIndex, rowIndex));
+      } else if (preprocessingData.VariableHasType<string>(columnIndex)) {
+        return string.IsNullOrEmpty(preprocessingData.GetCell<string>(columnIndex, rowIndex));
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        return preprocessingData.GetCell<DateTime>(columnIndex, rowIndex).Equals(DateTime.MinValue);
+      } else {
+        throw new ArgumentException("cell in column " + columnIndex + " and row index " + rowIndex + " contains a non supported type.");
+      }
+    }
+
+    public IList<int> GetMissingValueIndices(int columnIndex) {
+      if (!MissingValueIndicies.ContainsKey(columnIndex)) {
+        if (preprocessingData.VariableHasType<double>(columnIndex)) {
+          MissingValueIndicies[columnIndex] = GetMissingValueIndices<double>(columnIndex);
+        } else if (preprocessingData.VariableHasType<string>(columnIndex)) {
+          MissingValueIndicies[columnIndex] = GetMissingValueIndices<string>(columnIndex);
+        } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+          MissingValueIndicies[columnIndex] = GetMissingValueIndices<DateTime>(columnIndex);
+        } else {
+          throw new ArgumentException("column " + columnIndex + " contains a non supported type.");
+        }
+      }
+      return MissingValueIndicies[columnIndex];
+    }
+
+    private IList<int> GetMissingValueIndices<T>(int columnIndex) {
+      List<int> missingIndices = new List<int>();
+
+      for (int row = 0; row < preprocessingData.Rows; ++row) {
+        if (IsMissingValue(columnIndex, row)) {
+          missingIndices.Add(row);
+        }
+      }
+
+      return missingIndices;
+    }
+
+    public IEnumerable<T> GetValuesWithoutNaN<T>(int columnIndex, bool considerSelection) {
+      if (considerSelection) {
+        var selectedRows = preprocessingData.Selection[columnIndex];
+
+        List<T> values = new List<T>();
+        foreach (var rowIdx in selectedRows) {
+          if (!IsMissingValue(columnIndex, rowIdx)) {
+            values.Add(preprocessingData.GetCell<T>(columnIndex, rowIdx));
+          }
+        }
+        return values;
+      } else {
+        if (!ValuesWithoutNaN.ContainsKey(columnIndex)) {
+          List<T> values = new List<T>();
+
+          for (int row = 0; row < preprocessingData.Rows; ++row) {
+            if (!IsMissingValue(columnIndex, row)) {
+              values.Add(preprocessingData.GetCell<T>(columnIndex, row));
+            }
+          }
+
+          ValuesWithoutNaN[columnIndex] = values;
+        }
+        return (IEnumerable<T>)ValuesWithoutNaN[columnIndex];
+      }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs	(revision 13508)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/Logic/StatisticsLogic.cs	(revision 13508)
@@ -0,0 +1,235 @@
+﻿#region License Information
+/* HeuristicLab
+ * Copyright (C) 2002-2015 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.Generic;
+using System.Linq;
+using HeuristicLab.Common;
+
+namespace HeuristicLab.DataPreprocessing {
+  public class StatisticsLogic {
+
+    private readonly ITransactionalPreprocessingData preprocessingData;
+    private readonly SearchLogic searchLogic;
+
+    public StatisticsLogic(ITransactionalPreprocessingData thePreprocessingData, SearchLogic theSearchLogic) {
+      preprocessingData = thePreprocessingData;
+      searchLogic = theSearchLogic;
+    }
+
+    public int GetColumnCount() {
+      return searchLogic.Columns;
+    }
+
+    public int GetRowCount() {
+      return searchLogic.Rows;
+    }
+
+    public int GetNumericColumnCount() {
+      int count = 0;
+
+      for (int i = 0; i < searchLogic.Columns; ++i) {
+        if (preprocessingData.VariableHasType<double>(i)) {
+          ++count;
+        }
+      }
+      return count;
+    }
+
+    public int GetNominalColumnCount() {
+      return searchLogic.Columns - GetNumericColumnCount();
+    }
+
+    public int GetMissingValueCount() {
+      int count = 0;
+      for (int i = 0; i < searchLogic.Columns; ++i) {
+        count += GetMissingValueCount(i);
+      }
+      return count;
+    }
+
+    public int GetMissingValueCount(int columnIndex) {
+      return searchLogic.GetMissingValueIndices(columnIndex).Count();
+    }
+
+    public T GetMin<T>(int columnIndex, bool considerSelection = false) where T : IComparable<T> {
+      var min = default(T);
+      if (preprocessingData.VariableHasType<T>(columnIndex)) {
+        var values = GetValuesWithoutNaN<T>(columnIndex, considerSelection);
+        if (values.Any()) {
+          min = values.Min();
+        }
+      }
+      return min;
+    }
+
+    public T GetMax<T>(int columnIndex, bool considerSelection = false) where T : IComparable<T> {
+      var max = default(T);
+      if (preprocessingData.VariableHasType<T>(columnIndex)) {
+        var values = GetValuesWithoutNaN<T>(columnIndex, considerSelection);
+        if (values.Any()) {
+          max = values.Max();
+        }
+      }
+      return max;
+    }
+
+    public double GetMedian(int columnIndex, bool considerSelection = false) {
+      double median = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        var values = GetValuesWithoutNaN<double>(columnIndex, considerSelection);
+        if (values.Any()) {
+          median = values.Median();
+        }
+      }
+      return median;
+    }
+
+    public double GetAverage(int columnIndex, bool considerSelection = false) {
+      double avg = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        var values = GetValuesWithoutNaN<double>(columnIndex, considerSelection);
+        if (values.Any()) {
+          avg = values.Average();
+        }
+      }
+      return avg;
+    }
+
+    public DateTime GetMedianDateTime(int columnIndex, bool considerSelection = false) {
+      DateTime median = new DateTime();
+      if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        median = GetSecondsAsDateTime(GetDateTimeAsSeconds(columnIndex, considerSelection).Median());
+      }
+      return median;
+    }
+
+    public DateTime GetAverageDateTime(int columnIndex, bool considerSelection = false) {
+      DateTime avg = new DateTime();
+      if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        avg = GetSecondsAsDateTime(GetDateTimeAsSeconds(columnIndex, considerSelection).Average());
+      }
+      return avg;
+    }
+
+    public T GetMostCommonValue<T>(int columnIndex, bool considerSelection = false) {
+      var values = GetValuesWithoutNaN<T>(columnIndex, considerSelection);
+      if (!values.Any())
+        return default(T);
+      return values.GroupBy(x => x)
+                              .OrderByDescending(g => g.Count())
+                              .Select(g => g.Key)
+                              .First();
+    }
+
+
+    public double GetStandardDeviation(int columnIndex) {
+      double stdDev = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        stdDev = GetValuesWithoutNaN<double>(columnIndex).StandardDeviation();
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        stdDev = GetDateTimeAsSeconds(columnIndex).StandardDeviation();
+      }
+      return stdDev;
+    }
+
+    public double GetVariance(int columnIndex) {
+      double variance = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        variance = GetValuesWithoutNaN<double>(columnIndex).Variance();
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        variance = GetDateTimeAsSeconds(columnIndex).Variance();
+      }
+      return variance;
+    }
+
+    public double GetOneQuarterPercentile(int columnIndex) {
+      double percentile = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        percentile = GetValuesWithoutNaN<double>(columnIndex).Quantile(0.25);
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        percentile = GetDateTimeAsSeconds(columnIndex).Quantile(0.25);
+      }
+      return percentile;
+    }
+
+    public double GetThreeQuarterPercentile(int columnIndex) {
+      double percentile = double.NaN;
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        percentile = GetValuesWithoutNaN<double>(columnIndex).Quantile(0.75);
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        percentile = GetDateTimeAsSeconds(columnIndex).Quantile(0.75);
+      }
+      return percentile;
+    }
+
+    public int GetDifferentValuesCount<T>(int columnIndex) {
+      return preprocessingData.GetValues<T>(columnIndex).GroupBy(x => x).Count();
+    }
+
+    public int GetRowMissingValueCount(int rowIndex) {
+      int count = 0;
+      for (int i = 0; i < preprocessingData.Columns; ++i) {
+        if (searchLogic.IsMissingValue(i, rowIndex)) {
+          ++count;
+        }
+      }
+      return count;
+    }
+
+    public string GetVariableName(int columnIndex) {
+      return preprocessingData.GetVariableName(columnIndex);
+    }
+
+    public bool VariableHasType<T>(int columnIndex) {
+      return preprocessingData.VariableHasType<T>(columnIndex);
+    }
+
+    public string GetColumnTypeAsString(int columnIndex) {
+      if (preprocessingData.VariableHasType<double>(columnIndex)) {
+        return "double";
+      } else if (preprocessingData.VariableHasType<string>(columnIndex)) {
+        return "string";
+      } else if (preprocessingData.VariableHasType<DateTime>(columnIndex)) {
+        return "DateTime";
+      }
+      return "Unknown Type";
+    }
+
+    private IEnumerable<double> GetDateTimeAsSeconds(int columnIndex, bool considerSelection = false) {
+      return GetValuesWithoutNaN<DateTime>(columnIndex, considerSelection).Select(x => (double)x.Ticks / TimeSpan.TicksPerSecond);
+    }
+
+    private IEnumerable<T> GetValuesWithoutNaN<T>(int columnIndex, bool considerSelection = false) {
+      return searchLogic.GetValuesWithoutNaN<T>(columnIndex, considerSelection);
+    }
+
+    private DateTime GetSecondsAsDateTime(double seconds) {
+      DateTime dateTime = new DateTime();
+      return dateTime.AddSeconds(seconds);
+    }
+
+    public event DataPreprocessingChangedEventHandler Changed {
+      add { preprocessingData.Changed += value; }
+      remove { preprocessingData.Changed -= value; }
+    }
+  }
+}
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/PreprocessingContext.cs	(revision 13508)
@@ -35,25 +35,4 @@
     public string Filename { get; set; }
 
-    public IEnumerable<KeyValuePair<string, Func<IItem>>> ExportPossibilities {
-      get {
-        var algorithm = Source as IAlgorithm;
-        if (algorithm != null)
-          yield return new KeyValuePair<string, Func<IItem>>(algorithm.GetType().GetPrettyName(), () => ExportAlgorithm(algorithm));
-
-        var problem = algorithm != null ? algorithm.Problem as IDataAnalysisProblem : Source as IDataAnalysisProblem;
-        if (problem != null)
-          yield return new KeyValuePair<string, Func<IItem>>(problem.GetType().GetPrettyName(), () => ExportProblem(problem));
-
-        var problemData = problem != null ? problem.ProblemData : Source as IDataAnalysisProblemData;
-        if (problemData != null)
-          yield return new KeyValuePair<string, Func<IItem>>(problemData.GetType().GetPrettyName(), () => ExportProblemData(problemData));
-
-        // ToDo: Export CSV
-      }
-    }
-    public bool CanExport {
-      get { return Source is IAlgorithm || Source is IDataAnalysisProblem || Source is IDataAnalysisProblemData; }
-    }
-
     [Storable]
     public IFilteredPreprocessingData Data { get; private set; }
@@ -62,11 +41,14 @@
     private IItem Source { get; set; }
 
+    public event EventHandler Reset;
 
-    public PreprocessingContext() : this(new RegressionProblemData()) {
-      Name = "Data Preprocessing";
+    #region Constructors
+    public PreprocessingContext()
+      : this(new RegressionProblemData()) {
     }
-    public PreprocessingContext(IItem source)
+    public PreprocessingContext(IDataAnalysisProblemData problemData, IItem source = null)
       : base("Data Preprocessing") {
-      Import(source);
+      if (problemData == null) throw new ArgumentNullException("problemData");
+      Import(problemData, source);
     }
 
@@ -79,19 +61,24 @@
       Data = cloner.Clone(original.Data);
     }
-
     public override IDeepCloneable Clone(Cloner cloner) {
       return new PreprocessingContext(this, cloner);
     }
+    #endregion
 
     #region Import
-    public void Import(IItem source) {
-      Source = source;
-      var namedSource = source as INamedItem;
-      if (namedSource != null) Name = "Preprocessing: " + namedSource.Name;
-
-      var dataSource = ExtractProblemData(source);
-      Data = new FilteredPreprocessingData(new TransactionalPreprocessingData(dataSource));
+    public void Import(IDataAnalysisProblemData problemData, IItem source = null) {
+      if (problemData == null) throw new ArgumentNullException("problemData");
+      if (source != null && ExtractProblemData(source) != problemData)
+        throw new ArgumentException("The ProblemData extracted from the Source is different than the given ProblemData.");
+      Source = source ?? problemData;
+      var namedSource = Source as INamedItem;
+      if (namedSource != null)
+        Name = "Preprocessing " + namedSource.Name;
+      Data = new FilteredPreprocessingData(new TransactionalPreprocessingData(problemData));
+      OnReset();
+      // Reset GUI:
+      // - OnContentChanged for PreprocessingView!
+      // event? task(async import)?
     }
-
     private IDataAnalysisProblemData ExtractProblemData(IItem source) {
       var algorithm = source as Algorithm;
@@ -103,13 +90,27 @@
 
     #region Export
-    public IItem Export() {
-      if (Source is IAlgorithm)
-        return ExportAlgorithm((IAlgorithm)Source);
-      if (Source is IDataAnalysisProblem)
-        return ExportProblem((IDataAnalysisProblem)Source);
-      if (Source is IDataAnalysisProblemData)
-        return ExportProblemData((IDataAnalysisProblemData)Source);
-      return null;
+    public bool CanExport {
+      get { return Source is IAlgorithm || Source is IDataAnalysisProblem || Source is IDataAnalysisProblemData; }
     }
+    public IEnumerable<KeyValuePair<string, Func<IItem>>> GetSourceExportOptions() {
+      var algorithm = Source as IAlgorithm;
+      if (algorithm != null)
+        yield return new KeyValuePair<string, Func<IItem>>(
+          algorithm.GetType().GetPrettyName(),
+          () => ExportAlgorithm(algorithm));
+
+      var problem = algorithm != null ? algorithm.Problem as IDataAnalysisProblem : Source as IDataAnalysisProblem;
+      if (problem != null)
+        yield return new KeyValuePair<string, Func<IItem>>(
+          problem.GetType().GetPrettyName(),
+          () => ExportProblem(problem));
+
+      var problemData = problem != null ? problem.ProblemData : Source as IDataAnalysisProblemData;
+      if (problemData != null)
+        yield return new KeyValuePair<string, Func<IItem>>(
+          problemData.GetType().GetPrettyName(),
+          () => ExportProblemData(problemData));
+    }
+
     private IAlgorithm ExportAlgorithm(IAlgorithm source) {
       var preprocessedAlgorithm = (IAlgorithm)source.Clone();
@@ -117,24 +118,29 @@
       preprocessedAlgorithm.Runs.Clear();
       var problem = (IDataAnalysisProblem)preprocessedAlgorithm.Problem;
-      SetNewProblemData(problem);
+      problem.ProblemDataParameter.ActualValue = CreateNewProblemData();
       return preprocessedAlgorithm;
     }
     private IDataAnalysisProblem ExportProblem(IDataAnalysisProblem source) {
       var preprocessedProblem = (IDataAnalysisProblem)source.Clone();
-      SetNewProblemData(preprocessedProblem);
+      preprocessedProblem.ProblemDataParameter.ActualValue = CreateNewProblemData();
       return preprocessedProblem;
     }
     private IDataAnalysisProblemData ExportProblemData(IDataAnalysisProblemData source) {
+      return CreateNewProblemData();
+    }
+
+    public IDataAnalysisProblemData CreateNewProblemData() {
       var creator = new ProblemDataCreator(this);
-      var preprocessedProblemData = creator.CreateProblemData(source);
-      preprocessedProblemData.Name = "Preprocessed " + source.Name;
-      return preprocessedProblemData;
-    }
-    private void SetNewProblemData(IDataAnalysisProblem problem) {
-      var data = ExtractProblemData(problem.ProblemData);
-      problem.ProblemDataParameter.ActualValue = data;
-      problem.Name = "Preprocessed " + problem.Name;
+      var oldProblemData = ExtractProblemData(Source);
+      var newProblemData = creator.CreateProblemData(oldProblemData);
+      newProblemData.Name = "Preprocessed " + oldProblemData.Name;
+      return newProblemData;
     }
     #endregion
+
+    protected virtual void OnReset() {
+      if (Reset != null)
+        Reset(this, EventArgs.Empty);
+    }
   }
 }
Index: /trunk/sources/HeuristicLab.DataPreprocessing/3.4/ProblemDataCreator.cs
===================================================================
--- /trunk/sources/HeuristicLab.DataPreprocessing/3.4/ProblemDataCreator.cs	(revision 13507)
+++ /trunk/sources/HeuristicLab.DataPreprocessing/3.4/ProblemDataCreator.cs	(revision 13508)
@@ -48,5 +48,7 @@
       IDataAnalysisProblemData problemData;
 
-      if (oldProblemData is RegressionProblemData) {
+      if (oldProblemData is TimeSeriesPrognosisProblemData) {
+        problemData = CreateTimeSeriesPrognosisData((TimeSeriesPrognosisProblemData)oldProblemData);
+      } else if (oldProblemData is RegressionProblemData) {
         problemData = CreateRegressionData((RegressionProblemData)oldProblemData);
       } else if (oldProblemData is ClassificationProblemData) {
@@ -69,4 +71,16 @@
     }
 
+    private IDataAnalysisProblemData CreateTimeSeriesPrognosisData(TimeSeriesPrognosisProblemData oldProblemData) {
+      var targetVariable = oldProblemData.TargetVariable;
+      if (!context.Data.VariableNames.Contains(targetVariable))
+        targetVariable = context.Data.VariableNames.First();
+      var inputVariables = GetDoubleInputVariables(targetVariable);
+      var newProblemData = new TimeSeriesPrognosisProblemData(ExportedDataset, inputVariables, targetVariable, Transformations) {
+        TrainingHorizon = oldProblemData.TrainingHorizon,
+        TestHorizon = oldProblemData.TestHorizon
+      };
+      return newProblemData;
+    }
+
     private IDataAnalysisProblemData CreateRegressionData(RegressionProblemData oldProblemData) {
       var targetVariable = oldProblemData.TargetVariable;
@@ -83,6 +97,7 @@
         targetVariable = context.Data.VariableNames.First();
       var inputVariables = GetDoubleInputVariables(targetVariable);
-      var newProblemData = new ClassificationProblemData(ExportedDataset, inputVariables, targetVariable, Transformations);
-      newProblemData.PositiveClass = oldProblemData.PositiveClass;
+      var newProblemData = new ClassificationProblemData(ExportedDataset, inputVariables, targetVariable, Transformations) {
+        PositiveClass = oldProblemData.PositiveClass
+      };
       return newProblemData;
     }
