short cut to subtract cells without replicating numbers

Hi guys, assume the following: Cell array mx (100x61), Cell array mn (100x61), Cell array a (100x61).
These cell arrays consists of multiple matrix tables. Matrix table 'a' has 7 columns and matrix table mx/mn have one column. I want to carry out the following calculation between the corresponding matrix tables in the cell array: (a{column7row n}-mn{n})/(mx{n}-mn{n}). n=n+1 which increases after each row.
For that purpose I have been given this formula on the forum: Hi guys, assume the following: Cell array mx (100x61), Cell array mn (100x61), Cell array a (100x61).
These cell arrays consists of multiple matrix tables. Matrix table a has 7 columns and matrix table mx/mn have one column. I want to carry out the following calculation between the corresponding matrix tables in the cell array: (a{column7row n}-mn{n})/(mx{n}-mn{n}). n=n+1 which increases after each row.
For that purpose I have been given this formula on the forum:
q = (a{1}(:,7)-mx{:})./(mx{:}-mn{:});
The formula is great but for that formula to work I had to replicate the numbers in the matrices of the cell array mx and mn with the following formula:
n=61
for f = 1:n
for k=1:length(mx)
mx{k, f} = [kron(mx{k, f}, ones(60, 1))];
end
end
n=61
for f = 1:n
for k=1:length(mn)
mn{k, f} = [kron(mn{k, f}, ones(60, 1))];
end
end
The problem is that this process uses a lot of memory. Is there a short cut to carry out the calculation without first replicating the cells.The replication was necessary as each matrix in the original mn/mk had 60 times less rows than in the matrices of cell array a, i.e. when mn{1,1} had 6000 rows then the corresponding cell in a{1,1} had 360000. So in order to carry out a calculation I had to replicate the rows in mn first. I want the calculation to be carried out with the corresponding replicated rows without replicating the actual rows.

4 Comments

I don't understand your non-standard terminology despite reading it several times. A matrix is (almost always) a 2D array. An array can be an array of any dimension : 1, 2, 3, 4 or whatever. Your cell arrays (mx, mn, and a) are matrices of cells because they are 2D arrays of individual cells. A "table" is a special type of variable in MATLAB where each column is one type of variable, but the different columns can be different data types. A cell is like a container that can hold any type of variable - think of it like a bucket, and read this for a better understanding. Cells can hold any variable type and each row and column doesn't have to be the same - it can vary on a cell by cell basis. You refer to "a" as a cell array sometimes, and a single "matrix table" at other times. Yet you also say "These cell arrays consists of multiple matrix tables." So now, you say "a" is several "matrix tables" (whatever those are) instead of one "matrix table." In your mind, what is a matrix table?. I'll assume "a" is a cell array that is a matrix of 100 rows of 61 columns where each element is a single cell. Now, what is in each cell? Is each cell that Kron/ones thing? And do you really need cells instead of a standard numerical multidimensional array?
you are right. I will correct the mistake.
a is a cell array (100x61) where each element is a single cell. Each cell has various number of rows and 7 columns.
mx/mn are cell arrays (100x61) is a cell array (100x61) where each element is a single cell. Each cell has various number of rows and 7 columns.
I did not use 'table format'. Just matrices (displayed as double) and cell array. the cell array mx/mn kill my memory. If there is an alternative for the cell array mx/mn then please let me know.
thanks
Consider the following example for the aforementioned post:
a = {randi(50,600,9)};
mx = {randi(50,10,1)};
mn = {randi(50,10,1)};
q = (a{1}(:,7)-mn{:})./(mx{:}-mn{:});
*matrix dimensions do not agree. So I do a replication:*
n=1
for f = 1:n
for k=1:length(mn)
mn{k, f} = [kron(mn{k, f}, ones(60, 1))];
end
end
n=1
for f = 1:n
for k=1:length(mx)
mx{k, f} = [kron(mx{k, f}, ones(60, 1))];
end
end
only then i can carry out the calculation:
q = (a{1}(:,7)-mn{:})./(mx{:}-mn{:});
_ *How can I carry the calculation for the variable q getting the same results without first replicating mx and mn?* _
thanks a lot for your help guys. I really appreciate it.
This seems to be a good example of where the OP is asking about solving a particular issue (something regarding loops and the Kronecker tensor product), but does not actually address their basic intention. The statements made, eg " a is a cell array (100x61) where each element is a single cell." indicate some basic misunderstanding of cell arrays (as based on the code they gave in the above comment, all of a, mn and mx are actually 1x1 cell arrays containing numeric arrays), so perhaps some loose interpretation is required of the problem...
Thus it seems that those cell arrays and for-loops are a red-herring: it appears that the question is essentially "how do I replicate an array X so that it is the same size as another array Y, thus allowing operation fn(X,Y) to be performed". Important is perhaps the request "...without replicating the actual rows": perhaps bsxfun would be a suitable solution? Certainly this could be done without resorting to loops and the like...

Sign in to comment.

 Accepted Answer

Based on my comment above (that the cell arrays and loops are red-herrings), then this simplifies down to "how to replicate the arrays mn and mx to the same size as a, then apply some function to them all". Of course, the answer is to not replicate them, but to use bsxfun instead:
a = randi(50,600,9);
mx = randi(50,10,1);
mn = randi(50,10,1);
q = bsxfun(@minus,reshape(a(:,7),10,[]),mx);
q = bsxfun(@rdivide,q,mx-mn);
q = reshape(q,[],1);
Note the last three lines are derived from the given function:
q = (a{1}(:,7)-mx{:})./(mx{:}-mn{:});
after removing the (useless?) cell array references. To get exactly the same behavior as the OP's code, it might be required to perform some nonconjugate transpose operations at some steps.

4 Comments

There is one question. once I reshape the code via
q = bsxfun(@minus,reshape(a(:,7),10,[]),mx);
then I want the first value of mx to be subtracted from the first ten values.
Thank you for accepting my answer: I genuinely hope to be of assistance to people when I write answers here, and it is nice to get some feedback.
You might need to add a transpose to get the effect that you want, but there remains some dimension-issues that need to be clarified: based on the matrices defined in your comment a(:,7) has size 600x1, whereas mx has size 10x1. Do you wish to subtract mx(1) either from
  1. the first sixty consecutive values of a, or
  2. every tenth value in a ?
Or, as pseudocode:
  1. q(1:60) = a(1:60) - mx(1) , or
  2. q(1:10:600) = a(1:10:600) - mx(1) ?
(Essentially this is a question of row or column major operation and expansion)
Both of these methods will evenly divide a(:,7) by the ten values given in mx, however if you subtract mx(1) from the first ten values, and mx(2) from the next ten, and so on, then there will be 500 values of a(:,7) left over once we reach the end of mx, and it is not clear how you want these remaining values to be dealt with.
you are right. I forgot to mention the condition that the rows of variable a are always a multiple of mx/mn. Thus
a = randi(50,600,9);
mx = randi(50,60,1);
mn = randi(50,60,1);
I wish to subtract mx(1) from the first ten consecutive values of a. q(1:10) = a(1:10) - mx(1) q(11:20)=a(11:20)-mx(2) ... q(591:600)=a(591:600)-mx(60).
Okay, thank you for clarifying that. I will answer your new question ;)

Sign in to comment.

More Answers (0)

Asked:

AA
on 26 Nov 2014

Commented:

on 1 Dec 2014

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!