I have a matrix A=[1,2,3] and a cell B={[1,2,3],[1,2,5],[1,2,6]}.
I would like the product of the matrix elements of a similar cell
that's mean A * B ={1*[1,2,3],2*[1,2,5],3*[1,2,6]};
Without loop in matlab
Here a few ways to multiply as you described:
% inputs
A = [1,2,3];
B = {[1,2,3],[1,2,5],[1,2,6]};
using for-loop:
C1 = cell(size(B));
for i=1:numel(C1)
C1{i} = A(i) * B{i};
end
using cellfun:
C2 = cellfun(#(a,b)a*b, num2cell(A), B, 'Uniform',false);
using bsxfun:
C3 = bsxfun(#times, A(:), cat(1,B{:}));
C3 = num2cell(C3,2)';
All results should be equal (output being a cell array):
assert(isequal(C1,C2,C3))
If I were to choose, I would stick with the for-loop. In this case it's likely faster and easiest to read.
Related
If I have two sequences A and B containing the elements a1, a2, ... and b1,b2, ... where a_i and b_i are of dimension 1xn and 1xm, respectively, then I want to make a new sequence C which contains: a_i(1)*b_i, a_i(2)*b_i, ... , a_i(n)*b_i. So for the ith element of C, I want to have the Kronecker product of the elements a_i and b_i. I want to code this in Matlab, but without a for-loop. For the case when b_i are scalars, the desired result is achieved with
C = A.*B
However, this does not work for non-scalar b_i's. So what I do now is for sequences of length L:
C = [];
for ii = 1:L
C = [C; kron(A(ii,:),B(ii,:))];
end
But I have the idea that this must be possible without a for loop. Here is my code using the symbolic toolbox:
clc; clear;
L = 5;
syms('a1',[L,1]);
syms('a2',[L,1]);
syms('b1',[L,1]);
syms('b2',[L,1]);
A = [a1,a2];
B = [b1,b2];
C1 = A.*B % only for size(B,2)=1
C2 = [];
for ii = 1:L
C2 = [C2;kron(A(ii,:),B(ii,:))];
end
C2
C3 = kron(A,B) % does not work
Here reshape and implicit expansion are used to compute the result:
C = reshape(B .* reshape (A, L, 1, []), L, []);
I have a series of arrays of equal length, and want to make a matrix for each data point of these, and perform some sort of operation such a multiplying the matrices.
a=ones(1,10);
b=3*ones(1,10);
c=zeros(1,10);
for i=1:10
A(i)=[a(i) a(i);
b(i) b(i)];
B(i)=[c(i) c(i)];
C(i)=B(i)*A(i);
end
Is this possible without using cells?
A = zeros(2,2,length(a));
B = zeros(length(a),:);
C = zeros(size(B));
for i=1:10
A(:,:,i)=[a(i) a(i);
b(i) b(i)];
B(i,:)=[c(i) c(i)];
C(i,:)=B(i,:)*A(:,:,i);
end
Note you can make A and B without loops:
aa = permute(A, [3,2,1]);
bb = permute(B, [3,2,1]);
A = [aa,aa;bb,bb];
B = [c.', c.'];
The code below is only for 2 cell arrays, named B and C
A=cellfun(#minus, B, C, 'UniformOutput', false)
I want to perform a loop to be able to perform substraction for all my cell arrays.
Example of B{i} and C{i} are below:
B{1}=[0.435]
B{2}=[0.333] [0.532]
B{3}=[0.021] [0.432] [0.312] //command window output
C{1}=[0.211]
C{2}=[0.243] [0.116]
C{3}=[0.553] [0.212] [0.375] //command window output
B{1}-C{1}
B{2}-C{2}
B{3}-C{3}
I tried to include {i} behind A , B and C to become something like:
A{i}=cellfun(#minus, B{i}, C{i}, 'UniformOutput' , false)
However, it seems like it's not working. Is there any solution for this? Thanks
EDIT:
You have unnecessary nested cell-arrays, i.e B is a cell-array of cell-arrays, and B{i} is a cell-array of numbers.
If you want to keep that format, here is one way to compute the result using cellfun (A will also be a cell-array of cell-arrays of numbers):
% exiting data
B = cell(3,1);
B{1} = {0.435};
B{2} = {0.333, 0.532};
B{3} = {0.021, 0.432, 0.312};
C = cell(3,1);
C{1} = {0.211};
C{2} = {0.243, 0.116};
C{3} = {0.553, 0.212, 0.375};
A = cellfun(#(b,c)cellfun(#minus, b, c, 'Uniform',false), B, C, 'Uniform',false);
Otherwise I suggest you cut down on the level of nesting, and use this instead:
% note the difference between square-brackets and curly-brackets
B = cell(3,1);
B{1} = [0.435];
B{2} = [0.333, 0.532];
B{3} = [0.021, 0.432, 0.312];
C = cell(3,1);
C{1} = [0.211];
C{2} = [0.243, 0.116];
C{3} = [0.553, 0.212, 0.375];
Now you can compute the result using a single cellfun (no nesting):
A = cellfun(#minus, B, C, 'Uniform',false)
Suppose I have a matrix A and I sort the rows of this matrix. How do I replicate the same ordering on a matrix B (same size of course)?
E.g.
A = rand(3,4);
[val ind] = sort(A,2);
B = rand(3,4);
%// Reorder the elements of B according to the reordering of A
This is the best I've come up with
m = size(A,1);
B = B(bsxfun(#plus,(ind-1)*m,(1:m)'));
Out of curiosity, any alternatives?
Update: Jonas' excellent solution profiled on 2008a (XP):
n = n
0.048524 1.4632 1.4791 1.195 1.0662 1.108 1.0082 0.96335 0.93155 0.90532 0.88976
n = 2m
0.63202 1.3029 1.1112 1.0501 0.94703 0.92847 0.90411 0.8849 0.8667 0.92098 0.85569
It just goes to show that loops aren't anathema to MATLAB programmers anymore thanks to JITA (perhaps).
A somewhat clearer way to do this is to use a loop
A = rand(3,4);
B = rand(3,4);
[sortedA,ind] = sort(A,2);
for r = 1:size(A,1)
B(r,:) = B(r,ind(r,:));
end
Interestingly, the loop version is faster for small (<12 rows) and large (>~700 rows) square arrays (r2010a, OS X). The more columns there are relative to rows, the better the loop performs.
Here's the code I quickly hacked up for testing:
siz = 10:100:1010;
tt = zeros(100,2,length(siz));
for s = siz
for k = 1:100
A = rand(s,1*s);
B = rand(s,1*s);
[sortedA,ind] = sort(A,2);
tic;
for r = 1:size(A,1)
B(r,:) = B(r,ind(r,:));
end,tt(k,1,s==siz) = toc;
tic;
m = size(A,1);
B = B(bsxfun(#plus,(ind-1)*m,(1:m).'));
tt(k,2,s==siz) = toc;
end
end
m = squeeze(mean(tt,1));
m(1,:)./m(2,:)
For square arrays
ans =
0.7149 2.1508 1.2203 1.4684 1.2339 1.1855 1.0212 1.0201 0.8770 0.8584 0.8405
For twice as many columns as there are rows (same number of rows)
ans =
0.8431 1.2874 1.3550 1.1311 0.9979 0.9921 0.8263 0.7697 0.6856 0.7004 0.7314
Sort() returns the index along the dimension you sorted on. You can explicitly construct indexes for the other dimensions that cause the rows to remain stable, and then use linear indexing to rearrange the whole array.
A = rand(3,4);
B = A; %// Start with same values so we can programmatically check result
[A2 ix2] = sort(A,2);
%// ix2 is the index along dimension 2, and we want dimension 1 to remain unchanged
ix1 = repmat([1:size(A,1)]', [1 size(A,2)]); %//'
%// Convert to linear index equivalent of the reordering of the sort() call
ix = sub2ind(size(A), ix1, ix2)
%// And apply it
B2 = B(ix)
ok = isequal(A2, B2) %// confirm reordering
Can't you just do this?
[val ind]=sort(A);
B=B(ind);
It worked for me, unless I'm understanding your problem wrong.
I have a column vector I want to convert to a cell array such as:
A = rand(10,1);
B = cell(10,1);
for i=1:10
B{i} = A(i);
end
B =
[0.6221]
[0.3510]
[0.5132]
[0.4018]
[0.0760]
[0.2399]
[0.1233]
[0.1839]
[0.2400]
[0.4173]
How can I do this without an explicit for loop?
I tried:
B{:} = A(:)
and
[B{:}] = deal(A)
with no luck...
Also if possible, how can I do the same thing for a matrix, i.e. have each element in a cell by itself?
Use the function num2cell:
B = num2cell(A);
Works with matrices too.