everyone!
I've got a problem when using function handle in Matlab.
suppose I get a function handle of a transform matrix, say
Tf = #(alpha)reshape([cos(alpha),-sin(alpha),sin(alpha),cos(alpha)],[2,2]);
and I have a alpha vector
alpha_list = [alpha1; alpha2; ...];
I want to get the result like
[Tf1; Tf2; ...];
I have tried the ways like
Tf(alpha_list) feval(Tf,alpha_list) bsxfun(Tf,alpha_list)
They all don't work
Is there an easy or magic way to do this?
Many thanks!
Edit:
Realized a way to make it faster and added explanation.
Using arrayfun allows you to apply the function tf to each element of the a individually.
It outputs as a cell array though so you need to convert it back to a matrix using cell2mat.
tf = #(alpha) [cos(alpha),sin(alpha);-sin(alpha),cos(alpha)];
Tf =#(a) cell2mat(arrayfun(#(A) tf(A), a, 'uni', 0));
so if you put in a 1xN vector you will get back a 2x2N matrix, if you put in a Nx1 vector you will get back a 2Nx2 matrix.
>> a = rand(2)
a =
6.323592462254095e-01 2.784982188670484e-01
9.754040499940953e-02 5.468815192049839e-01
>> Tf(a)
ans =
Columns 1 through 3
8.066353232983801e-01 5.910494524211303e-01 9.614693800974246e-01
-5.910494524211303e-01 8.066353232983801e-01 -2.749120425428361e-01
9.952467051120759e-01 9.738580986754016e-02 8.541503641387258e-01
-9.738580986754016e-02 9.952467051120759e-01 -5.200261103460884e-01
Column 4
2.749120425428361e-01
9.614693800974246e-01
5.200261103460884e-01
8.541503641387258e-01
>> Tf(a) - [tf(a(1,1)), tf(a(1,2)); tf(a(2,1)), tf(a(2,2))]
ans =
0 0 0 0
0 0 0 0
0 0 0 0
0 0 0 0
Call Tfs for the solution:
Tf = #(a)[cos(a),sin(a); -sin(a), cos(a)];
Tfs = #(a) reshape(Tf(reshape(a,[1,1,length(a)])),[2,2*length(a)])'
The key here is that I use reshape to point the vector in the 3rd dimension, so that it doesn't interfere with the 2 we're interested in. Then we can use reshape again on the output which will preserve the block structure you're looking for.
This way, calling Tfs([1,2,2]) will return:
0.5403 0.8415
-0.8415 0.5403
-0.4161 0.9093
-0.9093 -0.4161
-0.4161 0.9093
-0.9093 -0.4161
I should also point out that, if you're not concerned about speed very much, there are much simpler ways to do this using simple loops...
Edit:
I switched the sign on Tf(a) because it was putting out Tf(a)'. It is correct now.
Related
I have a matrix X with 3 columns. For the porous of the question X=randn(5,3).
I want to normalize the columns of X S.T. each column will have a 0 mean and a 1 std. I was using the following code:
X=(X-mean(X))./std(X);
I am getting an std of 1. My mean, however, is a very small value close to 0 but not essential 0. I tried playing a bit with the numbers to find an explanation:
X=1:15;
X=reshape(X,[5 3]);
mean(X-mean(X));
Which gives me 0 value for each column.
X=1:15;
X=reshape(X,[5 3]);
mean((X-mean(X))./std(X));
Which does not. But 0/anything is still 0. what am I missing?
Why am I not getting 0 values?
Are the values I am getting good enough for a pre-clustering algorithm normalization?
Here is a version that does what I think you're trying to do... you need to replicate the matrix because X-mean(X) isn't valid (if you're using the standard implementation)-- you can't subtract a 1x3 from a 5x3.
r = 5; c = 3;
X=randn(r,c);
Xm=repmat(mean(X),r,1);
Xstd = repmat(std(X),r,1);
Xn = (X-Xm)./Xstd;
mean(Xn)
std(Xn)
For me this prints out
ans =
1.0e-16 *
-0.6661 0 0.4441
ans =
1.0000 1.0000 1.0000
Which seems like exactly what you're looking for... note the 1e-16 multiplier on the mean values... this is essentially 0, with some floating point error.
The specific task I'm trying to achieve is hard to describe, so here's an example: given A and x
A = [1 2;
3 0;
3 5;
4 0];
x = [1 2 3];
I want the algorithm to output
output: [1 2]
meaning that all of the nonzero elements in rows 1 and 2 in A are in x.
I have done this using cell arrays and loops; however, A and x are very large and my approach is not at all efficient. Also, I can't seem to figure out how to rework ismember to give me what I want. What is the fastest/least memory intensive method?
EDIT: Apologies, my original example was too simplistic. It is corrected now.
The first answer is good, but I would recommend to not using arrayfun. There are more eloquent ways to do what you ask. Use ismember combined with all, then index into the matrix A when you're done. Basically, your problem is to determine if a row has all of the values found in x and ignoring the zero values. In this case, we can find all of the values in the matrix A that are actually zero, then use this to augment our result.
Using A as the first input and x as the second input will return a matrix of the same size as A that tells you whether an element in A is found in x. If you want to check if all elements in the matrix A for a row can be found in x, check if all elements in a row is 1. On top of this, find all of the elements that are zero, then with the output of ismember set these to 1. This can be done with using a logical OR. After, you can use all and check each row independently by using the output of ismember as the first input into all and setting the second argument to 2. This would then return all of the rows in the matrix A where any column is found in x ignoring any values that are zero for a row in A which is what you're looking for:
A = [1 2; 3 0; 4 0];
x = [1 2 3];
mask = ismember(A, x);
ind = all(mask | A == 0, 2);
I'm also in favour of one-liners. We can consolidate this into one line of code:
ind = all(ismember(A, x) | A == 0, 2);
Even shorter is to simply invert A. All zero elements become true and false otherwise:
ind = all(ismember(A, x) | ~A, 2);
ind would thus be:
>> ind
ind =
3×1 logical array
1
1
0
Since you want the actual row indices, you can just use find on top of this:
>> find(ind)
ans =
1
2
To verify, let's use your second example in your comments:
>> A = [1 2;3 5;4 0];
>> x = [1 2 3];
>> ind = all(ismember(A, x) | ~A, 2)
ind =
3×1 logical array
1
0
0
>> find(ind)
ans =
1
I think the best way to rework ismember is to make sure there are no "no members" by just checking for the nonzero elements in A.
arrayfun can do the work in a fast way. It uses the most efficient parallel computing for your specific machine. The following line should return the correct output:
find(arrayfun(#(a) sum(~ismember(A(a,A(a,:)>0),x)),1:size(A,1))==0)
Is this what you were looking for?
However, if your problem is related to memory, then you may have to break the arrayfun operation into pieces (1:floor(size(A,1)/2), floor(size(A,1)/2):size(A,1) or smaller chunks), since MATLAB puts a bunch of workers to do the task, and may use all your available RAM memory...
Say i have a 2D matrix A:
A = [ 1 1 0 0
1 0 0 0
1 1 1 0];
A is not necessarily binary, or even integer (i.e., floats are possible). I want to remove any column that contains uniform valued elements. In the above example, i would get:
1 0
0 0
1 1
To make this fully general, i'd like to allow the user to select the dimension along which rows/columns/slices are removed (i.e., with a DIM option).
Any ideas?
You could try using the min and max functions, which allow you to use the dim argument.
For example
index = min(A,[],1)==max(A,[],1);
A(:,index)=[];
will remove the columns you want. It is straightforward to do the same for rows
index = min(A,[],2)==max(A,[],2);
A(index,:)=[];
One-liner:
B = A(:,range(A)~=0); %//columns
The other one-liner is not that nice, and ugly one-liners should not be written down. :-) But is basically the same solution as S..'s, except is way more expensive (requires stats toolbox).
Please note that "generality" of subscript-based solutions doesn't extend to N-dimensional arrays as easily, because subscripting in ND arrays without checking beforehand the number of dimensions is difficult. Also, for the 1D arrays the notion of "uniformity" is a bit odd along the singleton dimension (the result is always empty).
Besides the neat solution provided by #S.. there is this simple hack also for your example:
for ii = 1:size(A,2)
T(ii) = all(A(:,ii) == sum(A(:,ii))/numel(A(:,ii)));
end
A(:,~T)
ans =
1 0
0 0
1 1
As suggested by #gariepy the right side of the equation can be replaced with mean function.
for ii = 1:size(A,2)
T(ii) = all( A(:,ii) == mean(A(:,ii)) );
end
A(:,~T)
A(:,~all(A == repmat(A(1,:),[size(A,1) 1])))
Inspired by #S.. but only checks if every element of the column equals the first element of the column. Seems like a little less work for the processor than finding the min and the max, and checking for equality.
I want want to do some string calculation using Matlab, and then stored the value in an matrix.
For numerical study, I often predefined the dimensions in Matlab using zeros to create a 4*4 array.
a = zeros(4)
Now I want to do the same thing for the symbolic matrix. Obviously zeros didn't work at this time.
I tried to copy the official tutorial at this page http://www.mathworks.com/help/symbolic/sym.html
a = sym('0' ,4) % error
Still didn't work.
Now I have do use the ugly code like this
a = sym('[0 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0]');
Since I will use iterations, and dimension of the matrix grows every time. This method is not convenient.
Do you have any ideas? Thanks a lot!
Num = sym(Num) converts a number or a numeric matrix Num to symbolic form.
a=sym(zeros(4,4))
Can't try but suspect that the variables get initialized as zero by default.
For example when using
a = sym('a' ,[2 2])
I have a MxN Matrix and would like to convert into a vector MNx1 with all the elements of the row from the Matrix as the elements of the Vector.
I tried using reshape but I was not successful.
Here is the small code snippet and the expected result.
S=[0 1
1 0
1 1
1 1 ]
Expected Result:
S_prime= [ 0 1 1 0 1 1 1 1]
P.S: Using a loop and concatenation is not an option, I am sure there is a easy straight forward technique, which I am not aware.
Thanks
You could try transposing S and using (:)
S = S'
S_prime = S(:)
or for a row vector:
S_prime = S(:)'
Reshape takes the elements column wise so transpose S before reshaping.
>> reshape(S',1,[])
ans =
0 1 1 0 1 1 1 1
reshape(S',1,prod(size(S)))
or shortcut
reshape(S',1,[])
But the question makes me wonder what your original problem is, and if this way really is part of the correct solution to the original problem.
Octave has a very nice function: vec().
The document at http://www.mathcs.emory.edu/~nagy/courses/fall10/515/KroneckerIntro.pdf states the following.
vector x = vec(X)
can be obtained with the MATLAB statement: x = reshape(X, q*n, 1)