I have a matrix called "featureMatrix". using size(featureMatrix) the result is: 11843 720. I want to shuffle the content of this matrix using randperm. First I choose the seed using rng(1). Then I use randperm: featureMatrixRnd = featureMatrix(randperm(length(featureMatrix))');. But it didn't work good. In fact if i write size(featureMatrixRnd) I obtain 11843 1, instead of 11843 720. why?
Because you used length, which selects the longest dimension. First use numel instead of length to get all elements, then reshape back to your original size:
OrgSize = size(featureMatrix);
featureMatrixRnd = randperm(numel(featureMatrix));
out = reshape(featureMatrix(featureMatrixRnd),OrgSize);
This answer is similar to Adriaan's, but does not require a reshape:
featureMatrix(:) = featureMatrix(randperm(numel(featureMatrix)));
This is the best solution:
rng(1);
idx = randperm(size(featureMatrix,1));
outfeatureMatrixRnd = featureMatrix(idx,:);
Using
OrgSize = size(featureMatrix);
featureMatrixRnd = randperm(numel(featureMatrix));
out = reshape(featureMatrix(featureMatrixRnd),OrgSize);
is not good, because I don't need to shuffle everythink independently
Related
I got two sparse matrices A and B, which have identical sparsity pattern (all nonzeros are at exactly the same locations):
i = randi(1000,[50,1]);
j = randi(1000,[50,1]);
a = rand(50,1);
b = rand(50,1);
A = sparse(i,j,a,1000,1000);
B = sparse(i,j,b,1000,1000);
I would like to calculate efficiently exp(A-B) only for the nonzeros, and save it back into A.
I tried to use spfun for that task:
f = #(x,y) exp(x-y);
A = spfun(f,A,B);
but I got an error in spfun saying: "Too many input arguments."
Can anyone suggest an efficient way to calculate it?
It should be calculated many times.
Thanks!
Edit: mikkola suggested A = spfun(#f,A-B) which solves the problem, but the question remains how to do it with a function of two variables that can't be solved using the same trick. For example:
g = #(x,y) x.*cos(y);
A = spfun(#g,A,B);
You can't use
A = spfun(#exp, A-B);
because for entries where A an B are equal you will get 0 instead of 1.
To solve that, you can compute the vector of exponentials at the nonzero components, and then build a sparse matrix from that:
A = sparse(i,j,exp(nonzeros(A)-nonzeros(B))); %// if you have i, j stored
or
A(find(A)) = exp(nonzeros(A)-nonzeros(B));
Edit
According to the documentation, spfun can take only two inputs: a function and one sparse matrix.
So you cannot do directly what you want to do. The best solution is probably what has been suggested in the comments, i.e.:
res = spfun(#exp, A-B);
Best,
Suppose, I have two arrays:
startIds = [x1, x2, x3]
endIds = [y1, y2, y3]
The two arrays have the same length and can be long. We may assume that (endIds(ii)-startIds(ii)) are the same for all positions ii. Is there any fast ways to generate multiple sequences without using for loop?
startIds(1):endIds(1)
startIds(2):endIds(2)
startIds(3):endIds(3)
Thanks!
-Thang
You can use arrayfun:
sequences = arrayfun(#(i, j) (i:j), startIds, endIds, 'un', 0);
You will get a cell array sequences, where sequences{k} = startIds(k):endIds(k).
Here's the fastest answer I got through Mathworks:
range = endIds(1) - startIds(1);
t3 = bsxfun(#plus, startIds(:), 0:range);
At the time of this writing, this is the only version that is faster than my for loop version, which is in turn faster than using arrayfun or ndgrid. See my detailed benchmark here:
http://www.mathworks.com/matlabcentral/answers/217205-fast-ways-to-generate-multiple-sequences-without-using-for-loop
You may also try having some fun with matrices,
First get the difference between each entry and the first one in startIds,
dif = startIds - startIds(1);
dif_m = repmat(dif,endIds-startIds+1,1);
Then make a matrix of your first sequence
multi_seq = repmat((startIds(1):endIds(1))',1,length(startIds));
Get the sequences,
multi_seq = multi_seq + dif_m;
I have a 3-dimensial matrix W of size 160x170x18 and I want to compute the difference
between each sucessive matrices inside W.
For example diff1 = W(:,:,1) - W(:,:,2) and diff2 = W(:,:,2) - W(:,:,3), etc ...
Next I want to select some special parts of the resulting matrices, For example:
NewDiff1 = [diff1(20:50,110:140); diff1(60:90,110:140)];
and the same thing for the other matrices.
finally I want to compute the mean of each matrix and the error as follow:
mean1 = mean(mean(NewDiff1));
er1 = 0.1-abs(mean1);
I succeeded to do this for each matrix alone, but prefer to do all at once in a for loop.
The expression
diff1 = diff(W,1,3)
will return, in your example, a 160*170*17 matrix where diffW(:,:,1) = W(:,:,2) - W(:,:,1), which isn't quite what you want. But
diff1 = (-1)*diff(W,1,3)
does, if my arithmetic is good, give you the differences you want. From there on you need something like:
newdiff1 = [diff1(20:50,110:140,:);diff1(60:90,110:140,:)];
and
means = mean(mean(newdiff1));
er1 = 0.1 - abs(mean1);
I haven't tested this thoroughly on matrices of the size you are working with, but it seems to work OK on smaller tests.
Store your matrices into a cell array and then just loop through the contents of the cell array and apply the same differencing logic to each thing. Be careful to use the {} syntax with a cell array to get its contents, rather than () which gives you the cell at a particular location.
I have a matrix with integers and I need to replace all appearances of 2 with -5. What is the most efficient way to do it? I made it the way below, but I am sure there is more elegant way.
a=[1,2,3;1,3,5;2,2,2]
ind_plain = find(a == 2)
[row_indx col_indx] = ind2sub(size(a), ind_plain)
for el_id=1:length(row_indx)
a(row_indx(el_id),col_indx(el_id)) = -5;
end
Instead of loop I I seek for something like: a(row_indx,col_indx) = -5, which does not work.
find is not needed in this case.
Use logical indexing instead:
a(a == 2) = -5
In case of searching whether a matrix is equal to inf you should use
a(isinf(a)) = -5
The general case is:
Mat(boolMask) = val
where Mat is your matrix, boolMask is another matrix of logical values, and val is the assignment value
Try this:
a(a==2) = -5;
The somewhat longer version would be
ind_plain = find(a == 2);
a(ind_plain) = -5;
In other words, you can index a matrix directly using linear indexes, no need to convert them using ind2sub -- very useful! But as demonstrated above, you can get even shorter if you index the matrix using a boolean matrix.
By the way, you should put semicolons after your statements if (as is usually the case) you're not interested in getting the result of the statement dumped out to the console.
The Martin B's method is good if you are changing values in vector. However, to use it in matrix you need to get linear indices.
The easiest solution I found is to use changem function. Very easy to use:
mapout = changem(Z,newcode,oldcode)
In your case: newA = changem(a, 5, -2)
More info: http://www.mathworks.com/help/map/ref/changem.html
Here's a trivial, unoptimised, probably slow implementation of changem from the Mapping Toolbox.
function mapout = changem(Z, newcode, oldcode)
% Idential to the Mapping Toolbox's changem
% Note the weird order: newcode, oldcode. I left it unchanged from Matlab.
if numel(newcode) ~= numel(oldcode)
error('newcode and oldcode must be equal length');
end
mapout = Z;
for ii = 1:numel(oldcode)
mapout(Z == oldcode(ii)) = newcode(ii);
end
end
tesconf is 3x3 matrix;
tes_avg = (diag(tesconf)./sum(tesconf,2));
example that the result of tes_avg is given [0.345;0.3423;0.483]
However, i wish to get average result of this 3 values, how should i change the code above?Please advise...
Simply avg = mean(tes_avg); (or directly tes_avg = mean(diag(tesconf)./sum(tesconf,2));).