diff --git a/src/Microsoft.Data.Analysis/DataFrameColumn.cs b/src/Microsoft.Data.Analysis/DataFrameColumn.cs
index 2f7fae57b4..f414051b31 100644
--- a/src/Microsoft.Data.Analysis/DataFrameColumn.cs
+++ b/src/Microsoft.Data.Analysis/DataFrameColumn.cs
@@ -212,7 +212,9 @@ public object this[long rowIndex]
///
/// Clones the column.
///
- /// The number of null values to append to the copied values.
+ ///
+ /// The number of null values to append to the copied values. Columns that do not support null values append default values instead.
+ ///
/// A new
public DataFrameColumn Clone(long numberOfNullsToAppend = 0) => CloneImplementation(numberOfNullsToAppend);
@@ -229,7 +231,9 @@ public object this[long rowIndex]
/// to process integer values in in reverse order;
/// otherwise, . This parameter does not affect a Boolean map.
///
- /// The number of null values to append after the selected values.
+ ///
+ /// The number of null values to append after the selected values. Columns that do not support null values append default values instead.
+ ///
/// A new
public DataFrameColumn Clone(DataFrameColumn mapIndices, bool invertMapIndices = false, long numberOfNullsToAppend = 0) => CloneImplementation(mapIndices, invertMapIndices, numberOfNullsToAppend);
diff --git a/src/Microsoft.Data.Analysis/DataFrameColumns/VBufferDataFrameColumn.cs b/src/Microsoft.Data.Analysis/DataFrameColumns/VBufferDataFrameColumn.cs
index b86c6d6367..a32d5f4b96 100644
--- a/src/Microsoft.Data.Analysis/DataFrameColumns/VBufferDataFrameColumn.cs
+++ b/src/Microsoft.Data.Analysis/DataFrameColumns/VBufferDataFrameColumn.cs
@@ -267,13 +267,35 @@ private VBufferDataFrameColumn CloneImplementation(PrimitiveDataFrameColumn
+ ///
+ /// Clones the column, selecting and ordering values according to .
+ ///
+ ///
+ /// A Boolean, , or column that determines which values to copy.
+ /// For a Boolean column, the value at each position selects the value at the same position when it is
+ /// . For an integer column, each value is a zero-based index into this column;
+ /// the map order determines the result order, and repeated indices produce repeated values.
+ ///
+ ///
+ /// to process integer values in in reverse order;
+ /// otherwise, . This parameter does not affect a Boolean map.
+ ///
+ ///
+ /// The number of default values to append after the selected values.
+ ///
+ /// A new .
public new VBufferDataFrameColumn Clone(DataFrameColumn mapIndices, bool invertMapIndices, long numberOfNullsToAppend)
{
return (VBufferDataFrameColumn)CloneImplementation(mapIndices, invertMapIndices, numberOfNullsToAppend);
}
- ///
+ ///
+ /// Clones the column.
+ ///
+ ///
+ /// The number of default values to append to the copied values.
+ ///
+ /// A new .
public new VBufferDataFrameColumn Clone(long numberOfNullsToAppend = 0)
{
return (VBufferDataFrameColumn)CloneImplementation(numberOfNullsToAppend);
@@ -299,6 +321,9 @@ protected override DataFrameColumn CloneImplementation(DataFrameColumn mapIndice
clone = Clone();
}
+ for (long i = 0; i < numberOfNullsToAppend; i++)
+ clone.Append(default);
+
return clone;
}
@@ -309,6 +334,9 @@ protected override DataFrameColumn CloneImplementation(long numberOfNullsToAppen
for (long i = 0; i < Length; i++)
ret[i] = this[i];
+ for (long i = 0; i < numberOfNullsToAppend; i++)
+ ret.Append(default);
+
return ret;
}
diff --git a/src/Microsoft.Data.Analysis/PrimitiveDataFrameColumn.cs b/src/Microsoft.Data.Analysis/PrimitiveDataFrameColumn.cs
index 696a0d0b6d..a41c917d90 100644
--- a/src/Microsoft.Data.Analysis/PrimitiveDataFrameColumn.cs
+++ b/src/Microsoft.Data.Analysis/PrimitiveDataFrameColumn.cs
@@ -547,14 +547,10 @@ public PrimitiveDataFrameColumn Clone(PrimitiveDataFrameColumn mapIndice
/// A new .
public PrimitiveDataFrameColumn Clone(IEnumerable mapIndices)
{
- IEnumerator rows = mapIndices.GetEnumerator();
PrimitiveDataFrameColumn ret = CreateNewColumn(Name);
- long numberOfRows = 0;
- while (rows.MoveNext() && numberOfRows < Length)
+ foreach (long rowIndex in mapIndices)
{
- numberOfRows++;
- var curRow = rows.Current;
- var value = _columnContainer[curRow];
+ var value = _columnContainer[rowIndex];
ret.Append(value);
}
return ret;
diff --git a/test/Microsoft.Data.Analysis.Tests/PrimitiveDataFrameColumnTests.cs b/test/Microsoft.Data.Analysis.Tests/PrimitiveDataFrameColumnTests.cs
index 0111a7a316..b15caf9b22 100644
--- a/test/Microsoft.Data.Analysis.Tests/PrimitiveDataFrameColumnTests.cs
+++ b/test/Microsoft.Data.Analysis.Tests/PrimitiveDataFrameColumnTests.cs
@@ -439,6 +439,20 @@ public void TestNotNullableColumnCloneWithIndicesMapAsEnumerableInt()
Assert.Equal(column[indicesMap[i]], clonedColumn[i]);
}
+ [Fact]
+ public void TestColumnCloneWithEnumerableIndicesLongerThanColumn()
+ {
+ var column = new Int32DataFrameColumn("Int column", values: new[] { 10, 20 });
+ var longIndicesMap = new long[] { 0, 1, 0 };
+ var intIndicesMap = new int[] { 1, 0, 1 };
+
+ PrimitiveDataFrameColumn longIndicesClone = column.Clone(longIndicesMap);
+ PrimitiveDataFrameColumn intIndicesClone = column.Clone(intIndicesMap);
+
+ Assert.Equal(new int?[] { 10, 20, 10 }, longIndicesClone);
+ Assert.Equal(new int?[] { 20, 10, 20 }, intIndicesClone);
+ }
+
[Fact]
public void TestNullableColumnCloneWithIndicesMapAndSmallerSize()
{
diff --git a/test/Microsoft.Data.Analysis.Tests/VBufferColumnTests.cs b/test/Microsoft.Data.Analysis.Tests/VBufferColumnTests.cs
index e84b324987..cb11a5005b 100644
--- a/test/Microsoft.Data.Analysis.Tests/VBufferColumnTests.cs
+++ b/test/Microsoft.Data.Analysis.Tests/VBufferColumnTests.cs
@@ -46,6 +46,29 @@ public void TestVBufferColumn_Indexer()
Assert.Equal(0, vBufferColumn[0].GetValues()[4]);
}
+ [Fact]
+ public void TestVBufferColumn_CloneAppendsDefaultValues()
+ {
+ var first = new VBuffer(2, new[] { 1, 2 });
+ var second = new VBuffer(2, new[] { 3, 4 });
+ var column = new VBufferDataFrameColumn("VBuffer", new[] { first, second });
+ var mapIndices = new Int32DataFrameColumn("Indices", new[] { 1 });
+
+ VBufferDataFrameColumn clone = column.Clone(numberOfNullsToAppend: 2);
+ VBufferDataFrameColumn mappedClone = column.Clone(mapIndices, invertMapIndices: false, numberOfNullsToAppend: 2);
+
+ Assert.Equal(4, clone.Length);
+ Assert.Equal(first.GetValues().ToArray(), clone[0].GetValues().ToArray());
+ Assert.Equal(second.GetValues().ToArray(), clone[1].GetValues().ToArray());
+ Assert.Equal(0, clone[2].GetValues().Length);
+ Assert.Equal(0, clone[3].GetValues().Length);
+
+ Assert.Equal(3, mappedClone.Length);
+ Assert.Equal(second.GetValues().ToArray(), mappedClone[0].GetValues().ToArray());
+ Assert.Equal(0, mappedClone[1].GetValues().Length);
+ Assert.Equal(0, mappedClone[2].GetValues().Length);
+ }
+
[X64Fact("32-bit doesn't allow to allocate more than 2 Gb")]
public void TestVBufferColumn_Indexer_MoreThanMaxInt()
{