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:

enter image description here

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: enter image description here

and matrix b:

enter image description here

gives matrix c:

enter image description here

Not sure how to do conditional check for column b to be non-zero before evaluating?

  • $\begingroup$ 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? $\endgroup$ Dec 30, 2012 at 2:22

3 Answers 3


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}]
  • $\begingroup$ @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. $\endgroup$
    – halirutan
    Dec 30, 2012 at 3:06
  • $\begingroup$ 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. $\endgroup$ Dec 31, 2012 at 3:03
  • 1
    $\begingroup$ @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. $\endgroup$
    – halirutan
    Dec 31, 2012 at 3:24
  • $\begingroup$ @sebastianc. Please see the updated function. $\endgroup$
    – halirutan
    Dec 31, 2012 at 3:32
  • $\begingroup$ 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? $\endgroup$ Dec 31, 2012 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};

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

a // MatrixForm
b // MatrixForm

Mathematica graphics

Mathematica graphics

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

Mathematica graphics

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[[1]] = a[[1]];

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

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

Transpose[c] // MatrixForm

Mathematica graphics

  • $\begingroup$ 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. $\endgroup$ Jan 2, 2013 at 14:05
  • $\begingroup$ @sebastian Sorry, I got my signs turned around. Please let me know if the result now matches your expectation. $\endgroup$
    – Mr.Wizard
    Jan 2, 2013 at 14:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.