Matlab: How to re-order (re-organize) a matrix - matlab

I have a random column matrix:
r = rand(1,300)';
I want to re-order it so that instead of having elements in the order of 1,2,3,...,300
I will have elements 1,11,21,31,...,291,2,12,22,32,...,292,3,13,33,...293,...,300.
In other words, I want to take every 10th value, beginning with 1 and put them in that order, then do the same for 2 with every 10th value. I know one way to do this is:
n = 10;
r = [r(1:n:numel(r)); r(2:n:numel(r)); r(3:n:numel(r));...;r(10:n:numel(r))]; % Skipped 4-9 in this example
But obviously, this is very cumbersome to do more than a couple of times. Is there something more efficient?
A loop should be easy, but I am not doing it correctly, it seems (I can see why this might not work, but I can't correct it).
(Here is what I tried:)
n = 10;
for i = 1:10
a = [r(i:n:numel(r))];
end
Any suggestions or help is greatly appreciated.

You can do it like this:
r = reshape(reshape(r, 10, 30)', 300, 1)
EDIT:
As pointed out by #LuisMendo on the comments, it's safer to use .' than ' to transpose the matrix, because if the matrix is complex, that could introduce a complex conjugation. Then, it would be safer to do it like this:
r = reshape(reshape(r, 10, 30).', 300, 1)

You could reshape it into 30x10 matrix, transpose, and take the flat index:
A = 1:300;
A = reshape(A,30,10);
A = A';
A = A(:);

Try this -
intv = 10; %%// Interval after which you intend to get the values consecutively
out = r(reshape(reshape(1:numel(r),intv,[])',1,[]))

Some of the other solutions posted are more efficient, but your idea was a good one. It requires a simple fix to work:
N = numel(r);
M = N/10;
a=[];
for ii = 1:M
a= [a r(ii:10:N)];
end
Hope this helps

Related

Reshaping MATLAB matrix in a particular way

I am working on a MATLAB code so that I can basically do this
To accomlish that, my code looks like this
A = [1:30]'; % Example matrix
rows = 3;
for i=1:(numel(A)-rows+1)
B(1:rows,i)=A(i:i+rows-1,1);
end
Can someone help me do the same in a simpler way? I am guessing there is a one-line command that can solve that (maybe I'm wrong).
Let A and rows be defined as in your code. I'm assuming the values in A are just an example. If they are always 1, 2, ..., some of the solutions below can be simplified.
A = [1:30].';
rows = 3;
Here are some approaches:
My choice:
B = A(bsxfun(#plus, (1:rows).', 0:numel(A)-rows));
An alternative:
B = conv2(A.', flip(eye(rows)));
B = B(:, rows:end-rows+1);
Slightly more inefficient:
B = hankel(A);
B = B(1:rows, 1:numel(A)-rows+1);
If you have the Image Processing Toolbox:
B = im2col(A, [rows 1], 'sliding');

A for/while/if program to create a vector of repeated elements

My task is to write a program to create a vector which has its first 10 elements to be 10, element 11-20 to be 20, element 21-30 to be 30, element 31-40 to be 40, & element 41-50 to be 50.
This is how i did it.
v=zeros(1,50);
for i = 1:10
v(i)=10;
end
for i =11:20
v(i)=20;
end
for i = 21:30
v(i)=30;
end
for i = 31:40
v(i)=40;
end
for i = 41:50
v(i)=50
end
How can I write this more efficiently? (I'm new to matlab and programming in general. I'm thinking about how to construct this using while or if loops instead but without being able to produce a more efficient code.)
As we're spit-balling ways of doing this, something a bit different (though likely not efficient):
v=sort(mod(10:10:500,50))+10;
Also a method similar to rayryeng's answer, though I think slightly more efficient (avoiding the call to bsxfun):
v = 10:10:50;
v = v(ones(10,1),:);
v = v(:)';
The solutions in the comments as well as Shai's are very good. This is primarily here for thinking outside of the box. A more exotic solution would be to use bsxfun, followed by unrolling the resulting matrix into a vector:
v = bsxfun(#times, 10:10:50, ones(10,1));
v = v(:).';
The dedicated function for this task since Matlab R2015a is repelem:
x = repelem(10:10:50,10)
and another alternative:
s = 10; m = 50;
x = meshgrid(s:s:m,ones(s,1))
x = x(:)
You can use cumsum:
v = zeros(1,50);
v(1:10:end) = 10;
v = cumsum(v)
Using kron:
v = kron(10:10:50,ones(1,10))
If you like modulo operations, you can
v = reshape( mod(reshape((0:49)',[5 10]),5)'+1, 1, [] )*10
I suppose it's a bit more efficient that sort+mod proposed by #MrAzzaman.

Matlab optimisation query, avoiding that repmat

This is a simple question, I can't see a better answer and maybe someone else can! Here is the code:
Example variables
nSim = 3000;
nRow = 10000;
data = zeros(1, 5, nRow);
data (:, 1:4, :) = rand(4, nRow)*0.5; % 4 columns of duration values
data (:, 5, :) = 1000; % 1 column of actual value
basis.increaseRate = 1 + (rand(nSim, 4)*0.1);
Example calculation
dataWithSim = repmat(data(:, 1:4,:),nSim, 1, 1);
increaseFactors = bsxfun(#power, basis.increaseRate, dataWithSim);
Values = bsxfun(#times, data(:,5,:), prod(increaseFactors,2));
The need to repmat feels wrong, but I can't see a way to avoid it.
effectively I'm doing increase^data and I really didn't want to have to loop through the two dimensions (sims or data rows). The dummy data can be ordered any way I choose, but the values output needs to be an nSim by nRow matrix.
Any ideas welcome. Thanks.
You don't really need to use that repmat. You can directly feed that "submatrix" from data like so -
increaseFactors = bsxfun(#power, basis.increaseRate, data(:,1:4,:));
bsxfun internally takes care of the expansion of the singleton dimensions, which is the first dimension (rows) of data in this case. Since basis.increaseRate has nSim rows and data(:,1,4,:) has one row, it would be expanded to have the same number of rows, i.e. nSim and thus does the job of repmat-ing/expanding internally.
Rest of the code stays the same.

How to overwrite part of a vector?

I am trying to rewrite part of a vector given that:
t = -10:.1:10
x = exp((-3.*t);
The length of x will be 201, and I want to rewrite the first 100 values.
The only way I've gotten to work is by doing this:
EDIT Fixed typo.
t = 0:.1:10;
x = exp((-3.*t); % EDIT: THERE WAS A TYPO HERE
z = zeros(1,100);
for k = 1 : 100
x(k) = z(k);
end
There are three questions. First: What is a faster and more efficient way of doing this? Second: What do I do if I don't want to overwrite the first part of the code but rather the middle or the second part? Third: Is there a way of utilizing the full range of t where t = -10:.1:10 and just ignoring the first half instead of writing a whole new variable for it?
First: Nothing else I've tried has been successful.
Second: The only way I can think to do that is to append the two vectors together, but then it doesn't overwrite the data, so that is a no go.
Third:I have tried an if statement and that didn't work at all.
Your code appears to assign something to y, then changes the value of x. I assume that is a typo - and not the problem you actually want to fix.
In general, if you have
t = -10:0.1:10; % my preference: t = linspace(-10,10,201);
and
y = exp(-3 * t );
but you want to set the first 100 elements of y to zero, you can then do
y(1:100) = 0;
If you wanted never to compute y(1:100) in the first place you might do
y = zeros(size(t));
y(101:end) = exp(-3 * t(101:end));
There are many variations on this. I think the above code samples address all three of your questions.
change your
for k = 1 : 100
x(k) = z(k); % i think it should be y(k) though
end
to
x(1:100) = 0;
You could use logical indexing; that is, you can use a logical statement to select elements of a vector/matrix:
t = -10:0.1:10;
x = exp((-3.*t);
x(t < 0) = 0;
This works for the middle of a matrix too:
x(t > -5 & t < 5) = whatever;

vector comparison and new assignment

I'd like to ask you question about some matlab code I wrote, But first of all tell you my problem. I have 2 vectors, Test Labels and Predicted labels and I want to compare them for classification reasons. Further more I want to allocate some labels new. so I have something like this 111121111 = 1 or 1122222222 =2 which I want to achieve. My code is
y = [];
for k = 10:length(predictedLabel)-10
y = [y; newlabel(predictedLabel, k, 5)];
end
and the function newlabel is
function [nl] = newlabel(x, n, L)
numClasses = 3;
x1 = x(n-L:n+L);
c = zeros(numClasses, 1);
for k=1:length(x1)
c(x1(k)) = c(x1(k))+1;
end
[~,nl]=max(c);
end
My problem is now that I result following vector lengths
predictedLabel = 4996*1;
k=4986*1;
y=4977*1;
and I can't see my mistake
Any help is appreciated even new ideas with probability estimations
Thanks
loop
1- when using the length function on a scalar value it gives 1 then the value inside the for loop becomes from 10:1-10 which is meaningless. (If you want to use decreasing step you should provide something like this 10:-1:1).
2- if you want to make a vector with the size of 4996x1 it would be like this : zeros(4996,1) or ones(4996,1) or sth like this.
3- tell us about your desired result and your error.... the description is not obvious to me.