Reputation: 2164
I need to apply a function over columns of a matrix. Let's say I have this matrix --
>> m = rand(3,3)
m =
0.8626 0.5661 0.8489
0.6830 0.1498 0.1401
0.0857 0.4775 0.3296
and two vectors of lower and upper bounds --
>> mins = [2 3 5]
mins =
2 3 5
>> maxs = [7 11 13]
maxs =
7 11 13
Now what I am doing is to split the matrix into columns --
>> cols = num2cell(m, 1)
cols =
[3x1 double] [3x1 double] [3x1 double]
Now what I was trying is to apply a function over each column that takes the lower and the upper bounds to normalize the column values, more specifically I want to normalize the column m(:,1)
with mins(1)
and maxs(1)
, m(:,2)
with mins(2)
and maxs(2)
... column m(:,n)
with mins(n)
and maxs(n)
and so on. My take was like this --
>> norm_cols = cellfun(@(c, lb, ub) (ub - lb) .* c + lb, cols, mins, maxs);
Error using cellfun
Input #3 expected to be a cell array, was double instead.
My question is such thing doable in matlab? and lets say it's doable, then how do I merge the splitted columns into matrix again?
Moreover, please note that I am aware of loops, but I do not want to use it (as my matrix can grow like 1000x1000), so please do not provide any solution that uses loop. Although I am not sure if function mapping could give better speed up than loops (that's another issue, but not for today).
Upvotes: 2
Views: 233
Reputation: 47402
Well, you could certainly do something like this
>> x = {[1; 2; 3]/10, [4; 5; 6]/10, [7; 8; 9]/10};
>> mins = {1.5 4.5 7.5};
>> maxs = {2.5 5.5 8.5};
>> y = cellfun(@(a, lb, ub) (ub-lb) * x + lb, x, mins, maxs, 'uniform', 0)
y =
[3x1 double] [3x1 double] [3x1 double]
>> [y{:}]
ans =
1.600000000000000 4.900000000000000 8.199999999999999
1.700000000000000 5.000000000000000 8.300000000000001
1.800000000000000 5.100000000000000 8.400000000000000
But it's even cooler to use bsxfun
to broadcast your arguments across the rows, without turning it into a cell array first
>> x = [1 4 7; 2 5 8; 3 6 9] / 10;
>> mins = [1.5 4.5 7.5];
>> maxs = [2.5 5.5 8.5];
>> y = bsxfun(@plus, bsxfun(@times, x, maxs-mins), mins);
Upvotes: 4