Copy vector to vector in Matlab - matlab

I have a simple question about how can I copy a vector into another. I have a vector with a length of 66x1 and then, another with a length of 2151x1. I want to copy the values from the first one in a exactly position on the other. I've tried that but it doesn't work.
inter= 66x1
out= 2151x1
for i=1:numel(inter)
out(101:167)= inter(i)
end
Also I've tried this:
for inter=(1:66);
out(101:167)=inter;
end
And this:
for k= (101:167)
out(k)=inter(1:66);
end
Am I doing wrong? Thanks in advance,

Let's say your vectors are
a = [1; 2; 3];
b = [4; 5; 6; 7; 8; 9];
for simplicity.
There is no need to use loops. You can just go ahead and do it like this:
startIdx = 2; %101 in your case
finalIdx = startIdx + size(a,1) - 1; % 166 in your case
b(startIdx:finalIdx) = a;
Then b would be:
b =
4
1
2
3
8
9
A very important point here is the -1 in finalIdx. You need to substract 1 from the final index.

Related

How can I turn Structure to n-dimensional matrix

I have 2 matrices.
First one is the names.
Names={'a','b','c'};
Second one is Numbers.
a=[1 3]; b=[4]; c=[2 4 5];
Then i have the structure names which is combination of names and numbers, and they are equal some random matrices with equal rows and columns.
For this case i have 6 combination (2*1*3) and it looks like =
a1.b4.c2=[7 8 9; 10 11 14];
a1.b4.c4=[2 4 5; 3 4 7];
a1.b4.c5=[3 2 11; 4 7 8];
a3.b4.c2=[1 1 1; 3 5 12];
a3.b4.c4=[2 7 9 ; 10 11 12];
a3.b4.c5=[4 2 7 ; 5 6 8];
I want to return this into n-dimensional matrix. In this case it is 5-dimensional which has to look like this;
(:,:,1,4,2)=[7 8 9; 10 11 14]; %%%% for a=1 b=4 c=2
(:,:,1,4,4)=[2 4 5; 3 4 7]; %%%% for a=1 b=4 c=4
(:,:,1,4,5)=[3 2 11; 4 7 8]; %%%% for a=1 b=4 c=5
(:,:,3,4,2)=[1 1 1; 3 5 12]; %%%% for a=3 b=4 c=2
(:,:,3,4,4)=[2 7 9 ; 10 11 12]; %%%% for a=3 b=4 c=4
(:,:,3,4,5)=[4 2 7 ; 5 6 8]; %%%% for a=3 b=4 c=5
I want to write a generalized code that helps me do this job for different numbers of names and numbers yet I couldnt do it. Hope you can help me! Thanks.
To get every combination of the possible numbers for each fields, use ndgrid.
[Numbers{1:3}] = ndgrid(a,b,c);
Having the numbered structures sitting in the workspace as you describe makes it messy to access them programmatically and you should avoid it if possible; however they can still be accessed using eval.
evalPattern = strjoin(strcat(Names,'%d'), '.'); % 'a%d.b%d.c%d'
firstNumbers = cellfun(#(n) n(1), Numbers); % [1 4 2]
firstElement = eval(sprintf(evalPattern,firstNumbers)); % returns the value of a1.b4.c2
result = nan([size(firstElement) size(Numbers{1}]);
for ii = 1:numel(Numbers{1})
iiNumbers = cellfun(#(n) n(ii), Numbers);
result(:,:,ii) = eval(sprintf(evalPattern,iiNumbers));
end
Ok, it took longer than I expected, but the following code should work for arbitrary number of names and numbers, given the following requirements:
At the moment, names are considered to be single characters - that could be tweaked by regexp or something like this.
All your ax.bx.cx.... can be stored in some superordinated structure by your application (beforehand).
Your struct always follows the presented order of ax.bx.cx..., and the matrix dimensions are equal.
So, the script is quite long and - I'm afraid - needs some explanation. Please just ask. The basic idea is to loop through the struct(s) as long as the particular "children" are still structs. That assures arbitrary "depth" of structs, i.e. number of names and numbers.
I expanded your data, so you see, that it also works for (a) additional names, (b) additional numbers, and (c) different matrix sizes. Of course, it also works on your original data.
Also, one doesn't need Names or Numbers in the beginning as these information are automatically extracted from the (has to be there superordinated) structure.
(Attention: Written in Octave. I tried to verify, that all functionality is available in Matlab, too. Please report any issues, if that's not the case. I will then refactor the code.)
% Structs given.
a1.b4.c2.d3 = ones(4, 4);
a1.b4.c4.d3 = ones(4, 4) * 2;
a1.b4.c5.d3 = ones(4, 4) * 3;
a1.b6.c2.d3 = ones(4, 4) * 4;
a1.b6.c4.d3 = ones(4, 4) * 5;
a1.b6.c5.d3 = ones(4, 4) * 6;
a2.b4.c2.d3 = ones(4, 4) * 7;
a2.b4.c4.d3 = ones(4, 4) * 8;
a2.b4.c5.d3 = ones(4, 4) * 9;
a2.b6.c2.d3 = ones(4, 4) * 10;
a2.b6.c4.d3 = ones(4, 4) * 11;
a2.b6.c5.d3 = ones(4, 4) * 12;
% REQUIREMENT: Store your structs in some superordinated struct.
super.a1 = a1;
super.a2 = a2;
% Initialize combined struct for names and numbers.
NamesNumbers = struct();
% Initialize Names cell array.
Names = {};
% Extract names and numbers from superordinated struct.
totalNames = 0;
totalNumbers = 1;
current = super;
while (isstruct(current))
fields = fieldnames(current);
totalNames = totalNames + 1;
totalNumbers = totalNumbers * numel(fields);
for iField = 1:numel(fields)
field = fields{iField};
name = field(1);
Names{totalNames} = name;
number = field(2:end);
if (isfield(NamesNumbers, name) == false)
NamesNumbers.(name) = str2num(number);
else
NamesNumbers.(name) = [NamesNumbers.(name) str2num(number)];
end
end
current = current.(fields{1});
if (isstruct(current) == false)
[nRows, nCols] = size(current);
end
end
% Extract all values from superordinated struct.
level = struct2cell(super);
while (isstruct([level{:}]))
level = struct2cell([level{:}]);
end
values = vertcat(level{:});
% Determine indices.
maxIdx = cellfun(#(x) max(x), struct2cell(NamesNumbers));
idx = zeros([totalNumbers, totalNames]);
factorProd = 1;
for iName = 1:totalNames
numbers = NamesNumbers.(Names{iName});
n = numel(numbers);
factorProd = factorProd * n;
inner = totalNumbers / factorProd;
resh = totalNumbers * n / factorProd;
outer = factorProd / n;
column = repmat(reshape(repmat(numbers, inner, 1), resh, 1), outer, 1);
START = (iName - 1) * totalNumbers + 1;
STOP = iName * totalNumbers;
idx(START:STOP) = column;
end
% Initialize output.
output = zeros([nRows nCols maxIdx']);
% Fill output with values.
for iIdx = 1:size(idx, 1)
temp = num2cell(idx(iIdx, :));
START = (iIdx - 1) * nRows + 1;
STOP = iIdx * nRows;
output(:, :, temp{:}) = values(START:STOP, :);
end

Is there any way to obtain different shuffled in randperm?

I have a matrix [1 2 3 4] and I want to shuffle it with randperm in few times but I want to obtain different matrices. For example
for i=1:4
m(i,:)=randperm(4);
end
will give me 4 rows with 4 columns but I want every row to be different from every other one; e.g. like this:
m(1,:)=[1 3 4 2]
m(2,:)=[2 3 1 4]
m(3,:)=[2 1 4 3]
m(4,:)=[4 3 2 3]
You can just check the existing rows to see if the current permutation already exists
m = zeros(4, 4);
counter = 1;
while counter < 4
new = randperm(4);
if ~ismember(new, m, 'rows')
m(counter, :) = new;
counter = counter + 1;
end
end
Another (memory intensive) approach would be to generate all permutations and then randomly select N of them
allperms = perms(1:4);
N = 4;
m = allperms(randsample(size(allperms,1), N), :);
You can easily use the MATLAB function ismember to check if the random permutation that you just created is already contained in your matrix.
So you can just try something like that:
for i=1:4
temp = randperm(4);
while ismember(m,temp,'rows')
temp = randperm(4);
end
m(i,:) = temp;
end

Raplacing for loop by a single line statement in MATLAB

I have this function which needs to be run hundreds of times. It contains a for loop which I am trying to remove to make the function faster. Can someone help me replace the loop by a single line command.
nn = 4;
T = [5 1 2; 5 2 3; 5 3 4; 5 4 1];
p = [0 0; 1 0; 1 1; 0 1; 0.5 0.5];
A = zeros(nn,1);
for i=1:nn
sctr = T(i,:); pT = p(sctr,:);
A(i) = 1/2*det([pT,ones(3,1)]);
end
Perhaps removing det and replacing it with actual formula to calculate the determinant will help?
The For loop solution you have is probably the fastest. Other options are:
B = [p(T',:),ones(3*size(T,1),1)]
C= mat2cell(B,[3,3,3,3],3)
D= cellfun(#det,C);
or also you can write instead of D this expression
D = arrayfun(#(x) det(C{x}), 1 : size(C, 1));
etc...
I think this would work (I couldn't test it since I don't have my environment with me)
pT = p(T(1:nn,:),:);
A = 1/2 * det([pT, ones(3, 1)]);
You can obviously do a one line code from the code above but this would be less readable.
If it doesn't work and you keep the for-loop, at least consider the matrix preallocation (for A, pT and sctr) this will speed up your program.

how to select specific index in 3rd matrix from third dimention in matlab

I know this is a simple question but difficult to formulate in one sentence to google the answer.So, I have a 3d matrix with size 2x2x3 like this
A(:,:,1) =[1 1; 1 1];
A(:,:,2) =[2 2; 2 2];
A(:,:,3) =[4 4; 4 4];
and matrix B with size 2x2
B = [ 1 2; 2 3];
What i need is to chose from each third dimension in A just one number using matrix B:
for i=1:2,
for j=1:2,
C(i,j) = A(i,j,B(i,j));
end
end
How to that in one line without a loop?
Not really a single line, but without a loop:
[I J] = ind2sub (size(B), 1:numel(B));
linInd = sub2ind (size (A), I, J, B(:)');
C = reshape (A(linInd), size(B));
Here is another variation:
[r,c,~] = size(A);
[J,I] = meshgrid(1:size(B,1), 1:size(B,2));
idx = reshape(I(:) + r*(J(:)-1) + r*c*(B(:)-1), size(B));
C = A(idx)

Matlab swap

I am trying to create a function that will swap a specific number in a matrix with a specific number in the same matrix. For examlpe, if I start with A = [1 2 3;1 3 2], I want to be able to create B = [2 1 3; 2 3 1], simply by telling matlab to swap the 1's with the 2's. Any advice would be appreciated. Thanks!
If you have the following matrix:
A = [1 2 3; 1 3 2];
and you want all the ones to become twos and the twos to become ones, the following would be the simplest way to do it:
B = A;
B(find(A == 1)) = 2;
B(find(A == 2)) = 1;
EDIT:
As Kenny suggested, this can even be further simplified as:
B = A;
B(A == 1) = 2;
B(A == 2) = 1;
Another way to deal with the original problem is to create a permutation vector indicating to which numbers should the original entries be mapped to. For the example, entries [1 2 3] should be mapped respectively to [2 1 3], so that we can write
A = [1 2 3; 1 3 2];
perm = [2 1 3];
B = perm(A)
(advantage here is that everything is done in one step, and that it also works for operations more complicated than swaps ; drawback is that all elements of A must be positive integers with a known maximum)
Not sure why you would to perform that particular swap (row/column interchanges are more common). Matlab often denotes ':' to represent all of something. Here's how to swap rows and columns:
To swap rows:
A = A([New order of rows,,...], :)
To Swap columns:
A = A(:, [New order of columns,,...])
To change the entire i-th column:
A(:, i) = [New; values; for; i-th; column]
For example, to swap the 2nd and 3rd columns of A = [1 2 3;1 3 2]
A = A(:, [1, 3, 2])
A = [1 2 3; 1 3 2]
alpha = 1;
beta = 2;
indAlpha = (A == alpha);
indBeta = (A == beta);
A(indAlpha) = beta;
A(indBeta ) = alpha
I like this solution, it makes it clearer what is going on. Less magic numbers, could easily be made into a function. Recycles the same matrix if that is important.
I don't have a copy of MatLab installed, but I think you can do some thing like this;
for i=1:length(A)
if (A(i)=1), B(i) = 2, B(i)=A(i)
end
Note, that's only convert 1's to 2's and it looks like you also want to convert 2's to 1's, so you'll need to do a little more work.
There also probably a much more elegant way of doing it given you can do this sort of thing in Matlab
>> A = 1:1:3
A = [1,2,3]
>> B = A * 2
B = [2,4,6]
There might be a swapif primitive you can use, but I haven't used Matlab in a long time, so I'm not sure the best way to do it.
In reference to tarn's more elegant way of swapping values you could use a permutation matrix as follows:
>> a =[1 2 3];
>> T = [1 0 0;
0 0 1;
0 1 0];
>> b = a*T
ans =
1 3 2
but this will swap column 2 and column 3 of the vector (matrix) a; whereas the question asked about swapping the 1's and 2's.
Update
To swap elements of two different values look into the find function
ind = find(a==1);
returns the indices of all the elements with value, 1. Then you can use Mitch's suggestion to change the value of the elements using index arrays. Remeber that find returns the linear index into the matrix; the first element has index 1 and the last element of an nxm matrix has linear index n*m. The linear index is counted down the columns. For example
>> b = [1 3 5;2 4 6];
>> b(3) % same as b(1,2)
ans = 3
>> b(5) % same as b(1,3)
ans = 5
>> b(6) % same as b(2,3)
ans = 6