# How do I combine the data from two tables according to a rule of my own devising?

I have two matrices a = m x 5 and b =m x 5 (m is large, say 1,000) which are already sorted as below: How to generate a new matrix c = m x 5 which consists:

Column 1: exact replica of Column 1 of matrix a.
Column 2: Depends on non-zero elements of b as shown
so that it is adjusted by it's left hand side row of a - b + present row.
Zeros are not evaluated.

(example: 3.7107 - 2.96856 + 23.2988 = 24.0409 )

Columns 3 4 and 5, not sure yet so maybe start off with a SparseArray of m x 5? But most likely to be an extension of Column 2. i.e. Column 3,4 and 5 will be also adjusted once I have worked out how they need to adjusted by.

EDITED 31/12/2012 03:25am UK time:

Solution from @halirutan is partially correct because my input matrix a: and matrix b: gives matrix c: Not sure how to do conditional check for column b to be non-zero before evaluating?

• I like to but still learning how to format output matrix, can someone show me link as I was directed to meta link but still not clear how to format matrix output? – sebastian c. Dec 30 '12 at 2:22

Let me show you a way which hopefully helps you to solve such things alone next time. If you cannot implement your overall task, have you asked yourself, whether you can solve a sub-problem of your task? For instance, if you have one row of a and one row of b would you be able to combine this into the resulting row?

Basically, you are only interested in the first elements of each row. A combine function could look like the following

combine[{a1_, _, _, _, _}, {b1_, b2_, _, _, _}] :=
{a1, If[b2 != 0, a1 - b1 + b2, 0], 0, 0, 0}


The first entry in the result is a copy of of the first column of a and the second entry is the linear combination you described. I set the other ones to zero.

Now you want to apply this function to each a-b-row pair. For this you have to use a function which takes the appropriate rows from each matrix (first of a and b, second of a and b, ...) and applies combine. Exactly this is what MapThread is for

MapThread[combine, {a, b}]

• @NasserM.Abbasi, for this there are million ways but first comes, that the OP learns something and then, after a long while we maybe take a look at the speed of the implementation. Btw, 1000 rows are not critical. – halirutan Dec 30 '12 at 3:06
• Hi @halirutan this answer works but as Mr Wizard mentioned, does not treat my second column of zero elements well, it still does the a1 - b1 + b2 for the second column of elements even though that element is zero. As mentioned zero should simply be left as zero. if the second column of non-zero elements for matrix c must still be the same number of b non-zero elements. – sebastian c. Dec 31 '12 at 3:03
• @sebastianc. That's why I wrote "combine could look like" and "hopefully helps you to solve such things alone next time". Question: Can you change combine so that it fits your needs when there is a zero in the second column? The goal is to help you, not to do the homework. – halirutan Dec 31 '12 at 3:24
• @sebastianc. Please see the updated function. – halirutan Dec 31 '12 at 3:32
• Hi @halirutan could you show me how to do conditional in this case? I tried: combine[{a1_,,,,},{b1_,b2_,,,_}]:={a1,a1-b1+b2,0,0,0} /;b2!= 0 but no change? – sebastian c. Dec 31 '12 at 3:47

The matrix the way you specified it so far is an $m \times 2$ matrix with entries:

Transpose@{a[[All, 1]], a[[All, 1]] - b[[All,1]] + b[[All, 2]]}


To add the other columns, just extend the list above. This way of specifying whole columns by All in the first argument of Part ([[...]]) is the simplest thing I can think of given the fact that your manipulations seem to be formally the same for each row, i.e., they are just linear combinations of columns.

This problem appears to be an extension of your previous one:
Correct way to compare arrays and do conditional evaluations

Similarly to my answer there I advise that you use numeric methods where possible any time you are working with large matrices or where performance is important. halirutan shows a pattern-based method that is easy to read and understand (which earned it my vote) but it is not likely to scale well. (Also, his answer as written does not treat zeros the way I think you want based on the earlier answer.)

Here is an example using Part and Unitize. First create samples a and b:

dim = {2, 5, 5};

SeedRandom
{a, b} = RandomReal[10, dim] * RandomInteger[1, dim];

a // MatrixForm
b // MatrixForm  Build matrix c through a series of assignments:

c = ConstantArray[0, {5, 5}];

c[[All, 1]] = a[[All, 1]];

c[[All, 2]] = a[[All, 1]] - b[[All, 1]] + b[[All, 2]];

c[[All, 2]] *= Unitize @ b[[All, 2]];

c // MatrixForm If you are going to make frequent column-based changes to your data you would do well to Transpose it so that columns can be accessed without All. You can always use Transpose again to return the data to its original form.

{a, b} = Transpose /@ {a, b};

c = ConstantArray[0, {5, 5}];

c[] = a[];

c[] = a[] - b[] + b[];

c[] *= Unitize @ b[];

Transpose[c] // MatrixForm • Thanks @Mr Wizard but the logic is above, slightly different logic you have here. Take for example third row, second column it would be 7.89-8.34+4.71=4.26 and not 11.51 as shown, with a and b matrices ascending order left to right. – sebastian c. Jan 2 '13 at 14:05
• @sebastian Sorry, I got my signs turned around. Please let me know if the result now matches your expectation. – Mr.Wizard Jan 2 '13 at 14:38