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
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))=[]
For example, A = [19 20 21 22 23 24 25]; B = [2 0 3 0 0 0 2];
How can we get a new array, repeating each value from B accordingly X times?
For example, answer here is: [19 19 21 21 21 25 25].
Please note that I am only allowed to a for loop combined with a repmat call.
If you are only allowed to use repmat and a for loop, you can do the following:
S = [];
for idx = 1 : length(B)
S = [S repmat(A(idx), 1, B(idx))];
end
S is initially a blank array, then for as many values as there are in B (or A since they're both equal in length), simply concatenate S with each value in A that is repeated by the corresponding number in B. S will contain the output.
By running the above example, I get:
S =
19 19 21 21 21 25 25
However, I highly recommend you use more vectorized approaches. I'll leave that to you as an exercise.
Good luck!
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.
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.