Getting Original Indices of Reordered Array - arrays

I have an array of numbers A, and I want to create a new array B representing the indicies of A after A is reordered from smallest to largest.
For example:
A = [50 10 60 90 30];
The reordered A would then be:
A = [10 30 50 60 90];
And I want to get the output:
B = [2 5 1 3 4];
These indices in B therefore correspond to the original indices in A, but are written in the order of the reordered A.
How can I do this?

Use the second output of sort:
[A_sorted, B] = sort(A);

Related

reversing shuffling of array by indexing

I have a matrix whose columns which was shuffled according to some index. I know want to find the index that 'unshuffles' the array back into its original state.
For example:
myArray = [10 20 30 40 50 60]';
myShuffledArray = nan(6,3)
myShufflingIndex = nan(6,3)
for x = 1:3
myShufflingIndex(:,x) = randperm(length(myArray))';
myShuffledArray(:,x) = myArray(myShufflingIndex(:,x));
end
Now I want to find a matrix myUnshufflingIndex, which reverses the shuffling to get an array myUnshuffledArray = [10 20 30 40 50 60; 10 20 30 40 50 60; 10 20 30 40 50 60]'
I expect to use myUnshufflingIndex in the following way:
for x = 1:3
myUnShuffledArray(:,x) = myShuffledArray(myUnshufflingIndex(:,x), x);
end
For example, if one column in myShufflingIndex = [2 4 6 3 5 1]', then the corresponding column in myUnshufflingIndex is [6 1 4 2 5 3]'
Any ideas on how to get myUnshufflingIndex in a neat vectorised way? Also, is there a better way to unshuffle the array columnwise than in a loop?
You can get myUnshufflingIndex with a single call to sort:
[~, myUnshufflingIndex] = sort(myShufflingIndex, 1);
Alternatively, you don't even need to compute myUnshufflingIndex, since you can just use myShufflingIndex on the left hand side of the assignment to unshuffle the data:
for x = 1:3
myUnShuffledArray(myShufflingIndex(:, x), x) = myShuffledArray(:, x);
end
And if you'd like to avoid a for loop while unshuffling, you can vectorize it by adding an offset to each column of your index, turning it into a matrix of linear indices instead of just row indices:
[nRows, nCols] = size(myShufflingIndex);
myUnshufflingIndex = myShufflingIndex+repmat(0:nRows:(nRows*(nCols-1)), nRows, 1);
myUnShuffledArray = nan(nRows, nCols); % Preallocate
myUnShuffledArray(myUnshufflingIndex) = myShuffledArray;

Matlab: Creating a blockwise permutation

I have a vector from 1 to 40 and want to shuffle it in such a way that each block of four integers (ten blocks in total) are shuffled only with themselves.
For example: 3 4 2 1 | 7 6 5 8 | 9 11 10 12 | ...
My original idea was to append ten permutation vectors to eachother and then add a 1 to 40 vector to the big permutation vector, but it didn't work at all as expected and was logically wrong.
Has anyone an idea how to solve this?
data = 10:10:120; % input: values to be permuted
group_size = 4; % input: group size
D = reshape(data, group_size, []); % step 1
[~, ind] = sort(rand(size(D)), 1); % step 2
result = D(bsxfun(#plus, ind, (0:size(D,2)-1)*group_size)); % step 3
result = result(:).'; % step 4
Example result:
result =
20 10 30 40 60 50 70 80 110 100 120 90
How it works
Reshape the data vector into a matrix D, such that each group is a column. This is done with reshape.
Generate a matrix, ind, where each column contains the indices of a permutation of the corresponding column of D. This is done generating independent, uniform random values (rand), sorting each column, and getting the indices of the sorting (second output of sort).
Apply ind as column indices into D. This requires converting to linear indices, which can be done with bsxfun (or with sub2ind, but that's usually slower).
Reshape back into a vector.
You can use A = A(randperm(length(A))) to shuffle an array.
Example in Octave:
for i = 1:4:40
v(i:i+3) = v(i:i+3)(randperm(4));
end

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))=[]

Delete first n rows in column vector in Matlab & call array rows by an array of indices

I have 2 questions.
Question 1:
I have a column vector, v, with (say) 1000 rows. I want to delete first (say) n rows (for example n=300 to remove the first 300 rows of v).
Question 2:
I have an array of indices. How can it be used to get rows of another array whose index values are in first array?
I = [ 1 2 4 5] %// array of indices
Q = [ 45 22 66 87 99 10 ] %// input array
Desired Output:
O = [45 22 87 99] %// output array
For you first question:
N=300;
v=rand(1000,1); %// sample data
v(1:N)=[];
And the second:
O=Q(I)

summing over a matrix in different parts of that matrix in matlab

In a matrix, how can we sum part by part of the elements? Consider the primary matrix in a way that can be divided into smaller m by n matrix. then i want to sum the whole elements of each m by n matrix together and put the number instead of the m by n matrix
for example consider the following matrix, i want to sum every four elements and create another matrix:
A = [1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16];
And after summing i want to have:
B = [14 22
46 54];
I this example i summed 4 elements as a matrix of 2 by 2 then for example the result of summing 1,2,5 and 6 seats in the first element of the new matrix.
Let
m = 2; %// number of rows per block
n = 2; %// number of columns per block
You can do the sum with blockproc (from the Image Processing Toolbox), which is very suited for this task:
B = blockproc(A, [m n], #(x) sum(x.data(:)));
Or, if you build the appropriate indices, you can use accumarray:
[ii jj] = ndgrid(1:size(A,1), 1:size(A,2));
B = accumarray([ceil(ii(:)/n) ceil(jj(:)/m)], A(:))
One approach -
B = squeeze(sum(reshape(sum(reshape(A,m,[])),size(A,1)/m,n,[]),2))
Another approach if you would like to avoid squeeze, which is sometimes slower -
B = reshape(sum(reshape(reshape(sum(reshape(A,m,[])),size(A,1)/m,[])',n,[])),[],size(A,1)/m)'

Resources