calculation of value from given matrix - arrays

suppose that we have following array :
a=[12 21 23 10 34 54 10 9 5 6 7 8]
a =
12 21 23 10 34 54 10 9 5 6 7 8
length(a)=
length(a)
ans =
12
now i want to create following vector b ,which b(1),b(2)...b(6) are following
b(1)=sqrt(a(1)^2+a(2)^2)
b(2)=sqrt(a(3)^2+a(4)^2)
b(3)=sqrt(a(5)^2+a(6)^2))
b(4)=sqrt(a(7)^2+a(8)^2)
b(5)=sqrt(a(9)^2+a(10)^2))
b(6)=sqrt(a(11)^2+a(12)^2)
i have wrote following code
or i=2:2:length(a)
b(i/2)=sqrt(a(i-1)^2+a(i)^2);
end
>> b
b =
24.1868 25.0799 63.8122 13.4536 7.8102 10.6301
but i am not sure if it is correct,pleas help me to clarify if everything is ok in my code

In matlab, loops are quite slow. Using vectors is much faster. I suggest therefore a solution without a loop:
a_1 = a(1:2:end);
a_2 = a(2:2:end);
b = sqrt(a_1.^2 + a_2.^2);
first, you create a vector a_1 containing all elements with odd indices of a and a vector a_2 containing all elements with even indices.
Then you square them element wise (.^) and take the square of the sum.
For you example of a, this is 75 times faster. As you increase the size of the array, you will save even more time.

Related

Matlab: how do I apply a function along one dimension of an array

I have an array of mxnx4 dimensions and a function with a 4-element vector input. I want to apply my function to give me an mxnx4 output, such that the function is applied mxn times (i.e. the 3rd dimension of my array becomes in the input of my function). Any ideas on how do do this would be massively appreciated. I have looked at arrayfun, but this seems not to address what I want to do. I also want to maintain the formatting of my function as it requires this formatting elsewhere in my code.
I.e.:
F=#(V)[V(1)+V(2);V(2)+V(3); V(3)+V(4); V(4)+V(1)]
to be applied to array M of dimensions 2x3x4 (m=2; n=3)
M = zeros(2,3,4);
M(:,:,1) = [1 2 3;4 5 6];
M(:,:,2) = [7 8 9;10 11 12];
M(:,:,3) = [13 14 15; 16 17 18];
M(:,:,4) = [19 20 21; 22 23 24];
to generate an array of dimensions 2x3x4
C(1,1,:) = F([1 7 13 19])
C(1,2,:) = F([2 8 14 20])
etc.
I can see a for loop would work, applying the following across the mxn matrix
C(m,n,:)=F(M(m,n,:))
However, I need to run this millions of times so would like a faster approach

How to perform transpose to each page of nd array? [duplicate]

This question already has an answer here:
Matlab - Transpose a 3D matrix only in the third dimension
(1 answer)
Closed 5 years ago.
I am trying to figure out how to import large array of data into 3D matrix to a specific order. I have already asked two question but i have not get reliable answer yet and get down voted too. Since then i have done some work and was able to import data to 3D matrix using reshape function. Instead of shooting actual problem, this is a simulation of actual problem.
k=1:27 % create a array of 27 data
r=reshape(k,[3,3,3]) % convert the array into 3 x 3 x 3 matrix,
The results of the first page and second of the matrix is, the data is placed along the columns, but i wanted to place them along rows, The transpose function does not work with ND arrays, I tried to use permute but i did not get the desired result, One solution will be perform transpose to each page, but that will break the 3D matrix in to many 2D matrices.
r(:,:,1) =
1 4 7
2 5 8
3 6 9
r(:,:,2) =
10 13 16
11 14 17
12 15 18
the expected outcome should be,
r(:,:,1) =
1 2 3
4 5 6
7 8 9
Link to the actual problem is,
Thanks
Is this what you want?
result = permute(r, [2 1 3]);
This permutes the first two dimensions. For your example r,
>> k = 1:27;
>> r = reshape(k, [3,3,3]);
>> result = permute(r, [2 1 3]);
>> result
result(:,:,1) =
1 2 3
4 5 6
7 8 9
result(:,:,2) =
10 11 12
13 14 15
16 17 18
result(:,:,3) =
19 20 21
22 23 24
25 26 27

Delete values between specific ranges of indices in an array

I have an array :
Z = [1 24 3 4 52 66 77 8 21 100 101 120 155];
I have another array:
deletevaluesatindex=[1 3; 6 7;10 12]
I want to delete the values in array Z at indices (1 to 3, 6 to 7, 10 to 12) represented in the array deletevaluesatindex
So the result of Z is:
Z=[4 52 8 21 155];
I tried to use the expression below, but it does not work:
X([deletevaluesatindex])=[]
Another solution using bsxfun and cumsum:
%// create index matrix
idx = bsxfun(#plus , deletevaluesatindex.', [0; 1])
%// create mask
mask = zeros(numel(Z),1);
mask(idx(:)) = (-1).^(0:numel(idx)-1)
%// extract unmasked elements
out = Z(~cumsum(mask))
out = 4 52 8 21 155
This will do it:
rdvi= size(deletevaluesatindex,1); %finding rows of 'deletevaluesatindex'
temp = cell(1,rdvi); %Pre-allocation
for i=1:rdvi
%making a cell array of elements to be removed
temp(i)={deletevaluesatindex(i,1):deletevaluesatindex(i,2)};
end
temp = cell2mat(temp); %Now temp array contains the elements to be removed
Z(temp)=[] % Removing the elements
If you control how deletevaluesatindex is generated, you can instead directly generate the ranges using MATLAB's colon operator and concatenate them together using
deletevaluesatindex=[1:3 6:7 10:12]
then use the expression you suggested
Z([deletevaluesatindex])=[]
If you have to use deletevaluesatindex as it is given, you can generate the concatenated range using a loop or something like this
lo = deletevaluseatindex(:,1)
up = deletevaluseatindex(:,2)
x = cumsum(accumarray(cumsum([1;up(:)-lo(:)+1]),[lo(:);0]-[0;up(:)]-1)+1);
deleteat = x(1:end-1)
Edit: as in comments noted this solution only works in GNU Octave
with bsxfun this is possible:
Z=[1 24 3 4 52 66 77 8 21 100 101 120 155];
deletevaluesatindex = [1 3; 6 7;10 12];
idx = 1:size(deletevaluesatindex ,1);
idx_rm=bsxfun(#(A,B) (A(B):deletevaluesatindex (B,2))',deletevaluesatindex (:,1),idx);
Z(idx_rm(idx_rm ~= 0))=[]

Storing blocks of vector data into an array in Matlab

I have an array in Matlab
A = [1 2 3 4 5 6 7 8 9;
67 67 67 86 86 86 86 67 67]';
where every point in the first row of A corresponds to a "code" either 67 or 86. I am trying to extract these blocks of "67s" and "86s" such that every time a block starts the corresponding elements are put into the 3rd dimension of a different array called X, where the .
So for e.g. in A I have 3 different blocks, so I would like to end up with an array X of size 1x9x3. And for e.g. the first 67 block I would like to have X
X(1,:,1) = [1 2 3];
I understand that I would "fill up" this vector X using a for loop
for i=1:size(A,2)
for j=1:size(A,2) %actually j should be up till the number of blocks present
X(1,i,j) = A(1,i)
end
end
But this isn't correct or complete of course because firstly I'm unsure how to separate out the "blocks" and how to correctly "fill in" the j's in X(1,i,j). Secondly how can I get the code to recognise how many blocks there are?
Can anyone help?
Thanks
One possible approach, based on this answer:
>> B = accumarray([0; cumsum(diff(A(:,2)) ~= 0)] + 1, A(:,1), [], #(x) {x}, [])
Now you have this:
>> B{1}
ans =
1
2
3
>> B{2}
ans =
4
5
6
7
>> B{3}
ans =
8
9

Sort and keep index of a n-dimension array -- MATLAB

I have a 12-D array and am using each dimension as an index value in an optimization problem.
A(:,:,i1,i2,i3,i4,i5,i6,i7,i8,i9,i10)
each index value i is a value from 1 to 5.
I want to sort A from greatest to least and keep track of the indices so I know which indices correspond to to what value of A.
So my ideal output would be a 2 column cell/array with one column being the value and the other other column being the index values.
For a simple 3D example: say I have a 3D array: A(:,:,i1).
Where:
A(:,:,1) = 2
A(:,:,2) = 6
A(:,:,3) = 13
A(:,:,4) = 11
A(:,:,5) = 5
I would like my output to be:
13 3
11 4
6 2
5 5
2 1
EDIT:
assume I have 1x1x3x3 sized input such that
A(1,1,1,1) = 3
A(1,1,2,1) = 1
A(1,1,3,1) = 23
A(1,1,1,2) = 12
A(1,1,2,2) = 9
A(1,1,3,2) = 8
A(1,1,1,3) = 33
A(1,1,2,3) = 14
A(1,1,3,3) = 6
the expected output would be:
33 [1,1,1,3]
23 [1,1,3,1]
14 [1,1,2,3]
12 [1,1,1,2]
9 [1,1,2,2]
8 [1,1,3,2]
6 [1,1,3,3]
3 [1,1,1,1]
1 [1,1,2,1]
This should be a generic code for any multi-dimensional input array -
%// Sort A and get the indices
[sorted_vals,sorted_idx] = sort(A(:),'descend');
%// Set storage for indices as a cell array and then store sorted indices into it
c = cell([1 numel(size(A))]);
[c{:}] = ind2sub(size(A),sorted_idx);
%// Convert c to the requested format and concatenate with cell arary version of
%// sorted values for the desired output
out = [num2cell(sorted_vals) mat2cell([c{:}],ones(1,numel(A)),numel(size(A)))];
The generic code owes its gratitude to this fine solution.
I guess this is what you want:
b=A(:);
[sorted_b,ind]=sort(b,'descend');
[dim1,dim2,dim3,dim4]=ind2sub(size(A),ind);
%arranging in the form you want
yourCell=cell(size(b,1),2);
yourCell(:,1)=mat2cell(sorted_b,ones(size(b,1),1),1);
%arranging indices -> maybe vectorized way is there for putting values in "yourCell"
for i=1:size(b,1)
yourCell{i,2}=[dim1(i) dim2(i) dim3(i) dim4(i)];
end
For the array A, given by you, my output looks like:
33 [1,1,1,3]
23 [1,1,3,1]
14 [1,1,2,3]
12 [1,1,1,2]
9 [1,1,2,2]
8 [1,1,3,2]
6 [1,1,3,3]
3 [1,1,1,1]
1 [1,1,2,1]
which matches with your output.

Resources