STK++ 0.9.13
Arrays Tutorial 3 : Using Array2D

This page explain how you can add and or remove columns/rows to an array of the Array2D family and how to merge arrays with the same number of rows without duplicating data.

General features of the Arrays2D

The Array2D is a family of array/vectors/points propose many functionnalities allowing to assd/remove rows/columns. It is also possible to resize them in a conservative way. It is also possible to merge them if the dimension agreed.

Each columns in an Array2D is in a contiguous memory block. Thus, all operations on the columns is fast as it does not involve data copy. This is not the case for the rows. Inserting or appending rows will cause in the best cases a copy of the data. In the worse case, that is, if the number of rows required is greater than the capacities of the rows, it will even cause a re-allocation of a part or all the columns.

Adding rows and columns to Array2D

All the Array2D (That is the arrays deriving from the interface class STK::IArray2D) can add, insert, remove rows or columns to an existing data set.

  • A first example with the columns

    Adding columnsOutput
    #include "STKpp.h"
    using namespace STK;
    int main(int argc, char *argv[])
    {
    ArrayXX A(4, Range(0,2));
    Law::Normal law(1.,2.);
    A.rand(law);
    stk_cout << _T("A =\n") << A;
    // Adding a column with value 5
    A.pushFrontCols(Const::VectorX(4)*5);
    // insert an uninitialized columns at place 2
    A.insertCols(2, 2);
    // set x^2 and x^3 with x in columns 1
    A.col(2) = A.col(1).square();
    A.col(3) = A.col(1).cube();
    // add an uninitialized columns at the end
    A.pushBackCols(1);
    // set x^2 with x in columns 4
    A.col(5) = A.col(4).square();
    stk_cout << _T("A =\n") << A;
    // do the same with a vector
    VectorX B(4); B << 1, 3, 5, 6;
    stk_cout << _T("B = ") << B.transpose();
    // insert 1 uninitialized element in place 2
    B.insertElt(2); B[2] = 3; // set value to 3
    stk_cout << _T("B = ") << B.transpose();
    }
    #define stk_cout
    Standard stk output stream.
    #define _T(x)
    Let x unmodified.
    This file include all the header files of the STK++ project.
    Define the constant point.
    Normal distribution law.
    The MultidimRegression class allows to regress a multidimensional output variable among a multivariat...
    Index sub-vector region: Specialization when the size is unknown.
    Definition STK_Range.h:265
    The namespace STK is the main domain space of the Statistical ToolKit project.
    int main(int argc, char **argv)
    A =
    0.0615321 -0.617549
     -1.11315   2.73537
     -1.55495   1.97633
      3.92467   2.21783
    A =
    5 0.0615321 0.00378619 0.000232972 -0.617549 0.381367
    5  -1.11315    1.23911    -1.37932   2.73537  7.48223
    5  -1.55495    2.41786    -3.75965   1.97633   3.9059
    5   3.92467     15.403     60.4518   2.21783  4.91877
    B = 1 3 5 6
    B = 1 3 3 5 6
    

  • A Second example with the rows
    Adding rowsOutput
    #include "STKpp.h"
    using namespace STK;
    int main(int argc, char *argv[])
    {
    ArrayXX A(Range(0,2), 4);
    Law::Normal law(1.,2.);
    A.rand(law);
    stk_cout << _T("A =\n") << A;
    // Adding a column with 1
    A.pushFrontRows(Const::PointX(4));
    // Insert 2 uninitialize rows at place 2
    A.insertRows(2, 2);
    // Set x^2 and x^3 with x in row 1
    A.row(2) = A.row(1).square();
    A.row(3) = A.row(1).cube();
    // Add 2 unitialized rows
    A.pushBackRows(2);
    // Set x^2 and x^3 with x in row 4
    A.row(5) = A.row(4).square();
    A.row(6) = A.row(4).cube();
    stk_cout << _T("A =\n") << A;
    PointX B(4); B << 1, 3, 5, 6;
    stk_cout << _T("B =\n") << B;
    // insert an unitialized element at place 2
    B.insertElt(2); B[2] = 3; // set value to 3
    stk_cout << _T("B =\n") << B;
    }
    Define the constant point.
    A =
      5.01666   4.1416  1.91137 0.0289455
    -0.330411 0.837067 0.452249   4.28104
    A =
             1        1         1           1
       5.01666   4.1416   1.91137   0.0289455
       25.1669  17.1529   3.65332 0.000837844
       126.254  71.0404   6.98284 2.42518e-05
     -0.330411 0.837067  0.452249     4.28104
      0.109172 0.700682  0.204529     18.3273
    -0.0360715 0.586518 0.0924981     78.4598
    B =
    1 3 5 6
    B =
    1 3 3 5 6
    
Note
It is important to observe that adding/inserting columns to an Array2D does not produce any copy of the data stored, while the same operations involving the rows of the array will produce data movement.

The next graphic give the execution time of the following code

A.pushFrontCols(Const::VectorX(m));
A.insertCols(2, 2);
A.col(2) = A.col(1).square();
A.col(3) = A.col(1).cube();
A.pushBackCols(2);
A.col(5) = A.col(4).square();
A.col(6) = A.col(4).cube();

and of the same code by replacing "Cols" by "Rows". The size of the array A was (m,m). It is easily observed that adding rows is time consuming. Observe also that a small amount of space is added at the creation of the object and that the usage of the reserve method can be wise in order to save time.

Removing Rows and Columns

Rows and columns can be also removed from arrays of the Array2D family using remove and popBack methods.

Removing rows and columnsOutput:
#include "STKpp.h"
using namespace STK;
int main(int argc, char *argv[])
{
ArrayXX A(5, 6);
Law::Normal law(1.,2.);
A.rand(law);
stk_cout << _T("A =\n") << A;
// Remove 2 columns
A.popBackCols(2);
// erase two rows in position 1
A.eraseRows(1,2);
stk_cout << _T("A =\n") << A;
PointX B(6); B << 1, 2, 3, 4, 5, 6;
stk_cout << _T("B =\n") << B;
// erase three elements at the position 2
B.erase(2,3);
stk_cout << _T("B =\n") << B;
}
A =
-0.368484 -0.816883  2.29464 0.0968061 0.467136  1.46384
  1.44368   1.44231  2.00604 -0.447036  3.26891 -1.92511
  4.45443   3.14678  1.56722    2.2803  1.86343  1.84961
 -2.27432 -0.504987 -0.80423  -1.12455 0.381285  1.07171
 -2.01589   5.72782 0.884305  -3.11897  1.19921  3.89621
A =
-0.368484 -0.816883  2.29464 0.0968061
 -2.27432 -0.504987 -0.80423  -1.12455
 -2.01589   5.72782 0.884305  -3.11897
B =
1 2 3 4 5 6
B =
1 2 6

Merging two arrays

It is possible to merge an array with an other array or vector without copying the data using the merge method.

Merge an Array2D with an Array and a VectorOutput
#include "STKpp.h"
using namespace STK;
int main(int argc, char *argv[])
{
ArrayXX A(3, 2), B(3, 3);
A << 1, 2, 3, 4, 5, 6; B << 1, 2, 3, 4, 5, 6, 7, 8, 9;
stk_cout << _T("B.isRef() = ") << B.isRef() << _T('\n');
// merge B with A
A.merge(B);
stk_cout << _T("A =\n") << A << _T('\n');
stk_cout << _T("B.isRef() = ") << B.isRef() << _T('\n');
stk_cout << _T("B =\n") << B<< _T('\n');
// merge C with A
VectorX C(3); C << 4, 5, 6;
A.merge(C);
stk_cout << _T("A =\n") << A << _T('\n');
// B has been invalidate by A.merge(C) and cannot be used anymore
// stk_cout << _T("B =\n") << B; produce an error at execution
stk_cout << _T("C.isRef() = ") << C.isRef() << _T('\n');
stk_cout << _T("C =\n") << C;
}
B.isRef() = 0
A =
1 2 1 2 3
3 4 4 5 6
5 6 7 8 9

B.isRef() = 1
B =
1 2 3
4 5 6
7 8 9

A =
1 2 1 2 3 4
3 4 4 5 6 5
5 6 7 8 9 6

C.isRef() = 1
C =
4
5
6