diff --git a/src/Data/Text/DelimitedWriter.cs b/src/Data/Text/DelimitedWriter.cs index 42e09012..198cb52a 100644 --- a/src/Data/Text/DelimitedWriter.cs +++ b/src/Data/Text/DelimitedWriter.cs @@ -50,9 +50,11 @@ namespace MathNet.Numerics.Data.Text /// Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null. /// The number format to use on each element. Default: null. /// The culture to use. Default: null. + /// A value that represents a missing value. If not null, then elemements of the matrix that have this value + /// are not written to the output file. /// If either or is null. /// The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32. - public static void Write(TextWriter writer, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null) + public static void Write(TextWriter writer, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null, T? missingValue = null) where T : struct, IEquatable, IFormattable { if (matrix == null) @@ -78,20 +80,49 @@ namespace MathNet.Numerics.Data.Text var cols = matrix.ColumnCount - 1; var rows = matrix.RowCount - 1; - for (var i = 0; i < matrix.RowCount; i++) + if (!missingValue.HasValue) { - for (var j = 0; j < matrix.ColumnCount; j++) + for (var i = 0; i < matrix.RowCount; i++) { - writer.Write(matrix[i, j].ToString(format, formatProvider)); - if (j != cols) + for (var j = 0; j < matrix.ColumnCount; j++) { - writer.Write(delimiter); + writer.Write(matrix[i, j].ToString(format, formatProvider)); + + if (j != cols) + { + writer.Write(delimiter); + } } - } - if (i != rows) + if (i != rows) + { + writer.Write(Environment.NewLine); + } + } + } + else + { + var missing = missingValue.Value; + + for (var i = 0; i < matrix.RowCount; i++) { - writer.Write(Environment.NewLine); + for (var j = 0; j < matrix.ColumnCount; j++) + { + if (!matrix[i, j].Equals(missing)) + { + writer.Write(matrix[i, j].ToString(format, formatProvider)); + } + + if (j != cols) + { + writer.Write(delimiter); + } + } + + if (i != rows) + { + writer.Write(Environment.NewLine); + } } } } @@ -105,14 +136,16 @@ namespace MathNet.Numerics.Data.Text /// Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null. /// The number format to use on each element. Default: null. /// The culture to use. Default: null. + /// A value that represents a missing value. If not null, then elemements of the matrix that have this value + /// are not written to the output file. /// If either or is null. /// The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32. - public static void Write(string filePath, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null) + public static void Write(string filePath, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null, T? missingValue = null) where T : struct, IEquatable, IFormattable { using (var writer = new StreamWriter(filePath)) { - Write(writer, matrix, delimiter: delimiter, columnHeaders: columnHeaders, format: format, formatProvider: formatProvider); + Write(writer, matrix, delimiter: delimiter, columnHeaders: columnHeaders, format: format, formatProvider: formatProvider, missingValue: missingValue); } } @@ -125,14 +158,16 @@ namespace MathNet.Numerics.Data.Text /// Custom column header. Headers are only written if non-null and non-empty headers are provided. Default: null. /// The number format to use on each element. Default: null. /// The culture to use. Default: null. + /// A value that represents a missing value. If not null, then elemements of the matrix that have this value + /// are not written to the output file. /// If either or is null. /// The data type of the Matrix. It can be either: Double, Single, Complex, or Complex32. - public static void Write(Stream stream, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null) + public static void Write(Stream stream, Matrix matrix, string delimiter = "\t", IList columnHeaders = null, string format = null, IFormatProvider formatProvider = null, T? missingValue = null) where T : struct, IEquatable, IFormattable { using (var writer = new StreamWriter(stream)) { - Write(writer, matrix, delimiter: delimiter, columnHeaders: columnHeaders, format: format, formatProvider: formatProvider); + Write(writer, matrix, delimiter: delimiter, columnHeaders: columnHeaders, format: format, formatProvider: formatProvider, missingValue: missingValue); } } } diff --git a/src/DataUnitTests/Text/DelimitedWriterTests.cs b/src/DataUnitTests/Text/DelimitedWriterTests.cs index bc364ff3..604d32a4 100644 --- a/src/DataUnitTests/Text/DelimitedWriterTests.cs +++ b/src/DataUnitTests/Text/DelimitedWriterTests.cs @@ -151,5 +151,42 @@ namespace MathNet.Numerics.Data.UnitTests.Text + "0 0 9.9"; Assert.AreEqual(expected, text); } + + /// + /// Can write comma delimited data with missing values. + /// + [Test] + public void CanWriteCommaDelimitedDataWithMissingValues() + { + var matrix = SparseMatrix.OfArray(new[,] { { 1.1, 0, 0 }, { 0, 5.5, 0 }, { 0, 0, 9.9 } }); + var stream = new MemoryStream(); + DelimitedWriter.Write(stream, matrix, ",", missingValue: 0); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + var expected = @"1.1,," + Environment.NewLine + + ",5.5," + Environment.NewLine + + ",,9.9"; + Assert.AreEqual(expected, text); + } + + + /// + /// Can write space delimited data with missing values. + /// + [Test] + public void CanWriteTabDelimitedDataWithMissingValues() + { + var matrix = DenseMatrix.OfArray(new[,] { { 1.1, Double.NaN, 0 }, { 0, 5.5, 0 }, { Double.NaN, Double.NaN, 9.9 } }); + var stream = new MemoryStream(); + DelimitedWriter.Write(stream, matrix, "\t", missingValue: Double.NaN); + var data = stream.ToArray(); + var reader = new StreamReader(new MemoryStream(data)); + var text = reader.ReadToEnd(); + var expected = "1.1\t\t0" + Environment.NewLine + + "0\t5.5\t0" + Environment.NewLine + + "\t\t9.9"; + Assert.AreEqual(expected, text); + } } } \ No newline at end of file