how do i obtain multiple max values in an array simultaneously in matlab? - arrays

how do i obtain multiple max values in an array simultaneously in matlab?
for example in a row or column of a matrix
if I have an array [45 12 56 98 67 89 23 100 201 345]
how can i get the highest values simultaneosly

You can use unique which will by default sort the array in ascending order (so you'll want to flip it), then you can the first N values that you care about.
vals = flip(unique(data));
maxima = vals(1:N);
If you don't care about unique maxima, then just use sort instead.
vals = sort(data, 'descend');
maxima = vals(1:N);
If instead you want the maximum or minimum along a certain row/column, you can use the dim input to min or max.
% Maximum per column
maxima = max(data, [], 1);
% Maximum per row
maxima = max(data, [], 2);

Related

Array sorting in matlab

Hi i have a 289x2 array that i want to sort in MatLab. I want to sort the first column into numerical ascending order. However I want to keep the second column entry that is associated with it. Best way to explain is through an example.
x = 76 1
36 2
45 3
Now I want to sort x so that it returns an array that looks like:
x = 36 2
45 3
76 1
So the first column has been sorted into numerical order but has retained its second column value. So far I have tried sort(x,1). This sorts the first column as i want but does not keep the pairing. This returns x as:
x = 36 1
45 2
76 3
Any help would be great. Cheers!!
This is exactly what sortrows does.
x=sortrows(x); % or x=sortrows(x,1);
or if you want to use sort then get the sorted indexes first and then arrange the rows accordingly like this:
[~, idx] = sort(x); %Finding the sorted indexes
x = x(idx(:,1),:) ; %Arranging according to the indexes of the first column
Output for both approaches:
x =
36 2
45 3
76 1

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

MATLAB function to replace randi to generate a matrix

I have a matlab problem to solve. In have two vectores that limit my space, x_low and x_high. The matrix pos needs to have values within this spaces and each column of the matrix has different bounds given by the two vectores. Now my problem is that randi gives valus between two integers but i need to change the bounds for each columns. There is another way to use randi or a different matlab function to do this?
I know there are better codes to do this but i'm starting to use matlab and i know to do it this way, any aid is welcome
x_low = [Io_low, Iirr_low, Rp_low, Rs_low, n_low]; % vector of constant values
x_high = [Io_high, Iirr_high, Rp_high, Rs_high, n_high]; % vector of constant values
pos = rand(particles, var);
var = length(x_high);
for i = 1: particles % rows
for k = 1: var %columns
if pos(i, k) < x_low(k) || pos(i, k) > x_high(k) % if the position is out of bounder
pos(i, k) = randi(x_low(k), x_high(k), 1); % fill it with a particle whithin the bounderies
end
end
end
If I understand correctly, you need to generate a matrix with integer values such that each column has different lower and upper limits; and those lower and upper limits are inclusive.
This can be done very simply with
rand (to generate random numbers between 0 and 1 ),
bsxfun (to take care of the lower and upper limits on a column basis), and
round (so that the results are integer values).
Let the input data be defined as
x_low = [1 6 11]; %// lower limits
x_high = [3 10 100]; %// upper limits
n_rows = 7; %// number of columns
Then:
r = rand(n_rows, numel(x_low)); %// random numbers between 0 and 1
r = floor(bsxfun(#times, r, x_high-x_low+1)); %// adjust span and round to integers
r = bsxfun(#plus, r, x_low); %// adjust lower limit
gives something like
r =
2 7 83
3 6 93
2 6 22
3 10 85
3 7 96
1 10 90
2 8 57
If you need to fill in values only at specific entries of matrix pos, you can use something like
ind = bsxfun(#lt, pos, x_low) | bsxfun(#gt, pos, x_high); %// index of values to replace
pos(ind) = r(ind);
This a little overkill, because the whole matrixd r is generated only to use some of its entries. To generate only the needed values the best way is probably to use loops.
You can use cellfun for this. Something like:
x_low = [Io_low, Iirr_low, Rp_low, Rs_low, n_low];
x_high = [Io_high, Iirr_high, Rp_high, Rs_high, n_high];
pos = cell2mat(cellfun(#randi, mat2cell([x_low' x_high'], ones(numel(x_low),1), 1), repmat({[particles 1]}, [numel(x_low) 1)])))';
Best,

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)

find unique adjacent indices in 2d array

Assume I have a 2d array of objects, N x N. Assume that a pair can be made of every adjacent pair of objects, horizontally, vertically or diagonally. How can I count how many unique pairs there are for any value of N?
For example for N = 2
0 1
2 3
You can get 01 02 03 21 23 31, note that 03 is the same as 30
Is there a formula to determine how many of these pairs there are for a given N, and even better an algorithm for generating these?
Language is not that important but I will be using c++.
Using the below algorithm and eliminating duplicate indices, I get following counts. Not sure what the formula is yet.
For size N=2
Unique pairs is =6
For size N=3
Unique pairs is =20
For size N=4
Unique pairs is =42
For size N=5
Unique pairs is =72
For size N=6
Unique pairs is =110
For size N=7
Unique pairs is =156
For size N=8
Unique pairs is =210
For size N=9
Unique pairs is =272
Interesting, the formula appears to be 2^2+2, 4^2+4, 6^2+6, 8^2+8 ...
I find it easiest to pick a representative object of each type of pair (in other words, the top object of a vertical pair, the left most of a horizontal pair, and take your pick for diagonal pairs). This gives n(n-1) vertical pairs, n(n-1) horizontal pairs, and 2(n-1)^2 diagonal pairs (equal amounts of each variety). That totals up to 2(n-1)(n+n-1)=2(n-1)(2n-1), in agreement with your guess.
Each row has n-1 intra-row pairs and there are n rows.
Each column has n-1 intra-column pairs and there are n columns.
Each adjacent pair of rows have 2*(n-1) diagonal pairs and there are (n-1) adjacent row pairs.
Multiply and add these numbers and you will get your solution.
Here's the fixed formula for counting unique pairs.
(4 C 2)*(N-1)^2 - 2*(N-2)*(N-1)
Basically you just use the approach in dasblinkenlight's answer and subtract the "duplicate" edges. The duplicate edges will always be the edges between quadrants. I've added an explanation for the counting of duplicates below.
Using the original formula (4 C 2) * (N-1)**2 for N > 2, you will count duplicates. What you want to do is subtract these duplicate edges from the calculation.
Let's examine the simplest cases for N > 2. Suppose N = 3.
0-1-2
|x*x|
3*4*5
|x*x|
6-7-8
See the places where I marked an asterisk instead of an edge? Those edges will be counted twice by the formula. We can calculate them by breaking them up into horizontal and vertical edges. The number of vertical edges that are counted twice will be (N-2)*(N-1).
In the case of N=3, this will be 1 * 2 = 2. The number of horizontal edges that are counted twice will also be (N-2)*(N-1).
So if we simply add up the number of duplicate vertical edges and duplicate horizontal edges, we get
(N-2)*(N-1) + (N-2)*(N-1) = 2*(N-2)*(N-1)
We can simply subtract that number from our total to get the right number of edges.
Testing count in Python:
from math import factorial
def choose(n, k):
return factorial(n)/(factorial(k) * factorial(n-k))
for N in range(2, 10):
print choose(4, 2) * (N-1)**2 - 2 * (N-2) * (N-1)
The program prints:
6
20
42
72
110
156
210
272

Resources