I need to get the indices of the maximum values of the columns in a matrix, for example:
a =
16 2 3 13
5 11 10 8
9 7 6 12
4 14 15 1
and I want to get
[1, 4, 4, 1]
which are the indices of 16,14,15,13 i.e. the maximum value in each column. I discovered that
max(a,[],1)
returns
[16, 14, 15, 13]
How can I get their indices?
You need to find indices, not the numbers themselves, so you need the second output argument.
[~,I] = max(a)
Related
I have a vector of data for 21 years with daily data and want to create a rolling window of 365 days such as the next period stars one month (30 days) after the previous one. In the question, n_interval defines the difference between the first data point of the next window and the last observation of the previous series.
Let's assume my daily data start from Jan. 1 2000, then the first column would be Jan. 1, 2000 -Jan.1, 2001 and the second column starts from Feb. 1, 2000. and ends on Feb. 1, 2001. and ... the last column will cover Jan. 1, 2017 to Jan. 1, 2018. for example if:
vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17]
for a given variable n_interval = 3, with window_size=5, the output matrix should look like:
mat = [[1 4 7 10 13],
[2 5 8 11 14],
[3 6 9 12 15],
[4 7 10 13 16],
[5 8 11 14 17]]
Given your example vector
vec = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17];
we can create an indexing scheme by as follows:
First, we need to determine how many rows there will be in the mat. Assuming we want every element of vec to be expressed in mat at least once then we need to make sure that last index in the last row is greater than or equal to the size of vec. It's fairly easy to see that the index of the last column in mat is described by
last_index = n_interval*(n_rows-1) + n_columns
We want to ensure that last_index >= numel(vec). Substituting in the above expression into the inequality and solving for n_rows gives
n_rows >= (numel(vec) - n_columns)/n_interval + 1
We assign n_rows to be the ceil of this bound so that it is the smallest integer which satisfies the inequality. Now that we know the number of rows we generate the list of starting indices for each row
start_index = 1:n_interval:(n_interval*(n_rows-1)+1);
In the index matrix we want each column to be 1 plus the previous column. In other words we want to offset the column according to the array index_offset = 0:(n_interval-1).
Using bsxfun we generate the index matrix by computing the sums of all pairs between the start_index and index_offset arrays
index = bsxfun(#plus, index_offset, start_index');
The final thing we need to worry about is going out of bounds. To handle this we apply the mod function to wrap the out of bounds indicies:
index_wrapped = mod(index-1, numel(vec))+1;
Then we simply sample the vector according to index_wrapped
mat = vec(index_wrapped);
The complete code is
n_interval = 3;
n_columns = 5;
vec = 1:17;
n_rows = ceil((numel(vec)-n_columns)/n_interval + 1);
start_index = 1:n_interval:(n_interval*(n_rows-1)+1);
index_offset = 0:(n_columns-1);
index = bsxfun(#plus, index_offset, start_index');
index_wrapped = mod(index-1, numel(vec))+1;
mat = vec(index_wrapped);
Suppose I create the following matrix M.
>>>M = reshape(linspace(11,18,8),[2, 2, 2])
>>>M(:,:,1) =
11 13
12 14
M(:,:,2) =
15 17
16 18
>>>M([1,2],[2, 1],[2,1])
>>>
ans(:,:,1) =
17 15
18 16
ans(:,:,2) =
13 11
14 12
Please explain how the command M([1,2],[2, 1],[2,1]) produces the above result.explain the indexing in detail.
Let us start with simple example,
M([1,2],1,1) is going to show rows 1 and 2 of column 1 and 2d matrix 1.
ans =
11
12
M([2,1],1,1) is going to exchange rows 1 and 2 of column 1 and 2d matrix 1.
ans =
12
11
So changing the first index changes the rows order. Similarly Modifying second index will change the column order. And modifying third index will change the 2d matrices order.
Now let us take small example before we go to your problem,
M([1,2],[2,1],1)
Will exchange the columns of both rows of first 2d matrix.
ans =
13 11
14 12
And M([1,2],[1,2],[2,1]) will exchange between 1st 2d matrix and the second,
ans(:,:,1) =
15 17
16 18
ans(:,:,2) =
11 13
12 14
So combining the last two examples will exchange the 2d matrices and exchange their columns with keeping the orders of rows and that what exactly your answer shows
M([1,2],[2, 1],[2,1])
ans(:,:,1) =
17 15
18 16
ans(:,:,2) =
13 11
14 12
Hope this helps.
First, M is a three-dimensional matrix, which consists of two 2x2 matrix. So M(:,:,1) will get the first 2x2 matrix, and M(:,:,2) will get the second 2x2 matrix.
Some examples :
M(1, 2, 2) will give answer 17, which is the element in row 1 and column 2 of the 2nd matrix.
M(1, 1, [2, 1]) will give answers : 15 and 11 in that order. It will gather the element in row 1 and column 1, of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(1, 1, [1, 2]) will give answers : 11 and 15 in that order. It will gather the element in row 1 and column 1, of each from the two matrix in [1 2] order (so it will return from the 1st matrix first).
M(1, [1 2], [2, 1]) will give answers : 15 17 and 11 13 in that order. It will gather the element(s) in row 1 of column 1 & 2 (in this order), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(2, [1 2], [2, 1]) will give answers : 16 18 and 12 14 in that order. It will gather the element(s) in row 2 of column 1 & 2 (in this order), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
M(2, [1 1], [2, 1]) will give answers : 16 16 and 12 12 in that order. It will gather the element(s) in row 2 of column 1 & 1 (*same column), of each from the two matrix in [2 1] order (so it will return from the 2nd matrix first).
So,
M([1 2], [2 1], [2, 1]) will give answers :
17 15
18 16
( which means the output is a 2x2 matrix, with 1st column and 2nd column are 2nd column and 1st column (respectively, by [2 1]) of the 2nd matrix. The 1st row and 2nd row are 1st and 2nd rows (respectively, by [1 2]) of the 2nd matrix. )
and also
13 11
14 12
....
Also, you may want to read the documentation : https://www.mathworks.com/help/matlab/math/matrix-indexing.html
data = reshape(1:21504,[256,4,21]);
data(:,5:4:end)
I test some indexes, such as:
data(:,5:4:end) ~= data(:,5:4:end,1)
data(:,5:4:end) ~= data(:,1,5:4:end)
So what is the meaning of data(:,5:4:end)?
I test some other indexes, such as:
data(1,1) == data(1,1,1)
data(1,1:3) == data(1,1:3,1)
And find some strange behavior ,such as data(1,1:10,1) returns error but data(1,1:10) is ok.
So What's happening here?
How can I understand this mechanism?
>> size(data)
ans =
256 4 21
data(1,1:10,1) selects column 1-10 from first row (all three dimensions are explicitly set), but there are only 4 columns. Therefore the error.
data(1,1:10), on the other hand, uses Linear indexing, which interpretes dimensions 2 and 3 as one long strung of values and selects its first 10 values.
Linear Indexing
What does this expression A(14) do?
When you index into the matrix A using only one subscript, MATLAB treats A as if its elements were strung out in a long column vector, by going down the columns consecutively, as in:
16
5
9
...
8
12
1
The expression A(14) simply extracts the 14th element of the implicit column vector. Indexing into a matrix with a single subscript in this way is often called linear indexing.
Here are the elements of the matrix A along with their linear indices:
matrix_with_linear_indices.gif
The linear index of each element is shown in the upper left.
From the diagram you can see that A(14) is the same as A(2,4).
The single subscript can be a vector containing more than one linear index, as in:
A([6 12 15])
ans =
11 15 12
Consider again the problem of extracting just the (2,1), (3,2), and (4,4) elements of A. You can use linear indexing to extract those elements:
A([2 7 16])
ans =
5 7 1
That's easy to see for this example, but how do you compute linear indices in general? MATLAB provides a function called sub2ind that converts from row and column subscripts to linear indices. You can use it to extract the desired elements this way:
idx = sub2ind(size(A), [2 3 4], [1 2 4])
ans =
2 7 16
A(idx)
ans =
5 7 1
(Copied from http://de.mathworks.com/company/newsletters/articles/matrix-indexing-in-matlab.html)
data(:, 5:4:end) will access all elements in the first dimension of data and starting from index 5 every 4th index until the last index in the second dimension of data. The syntax for this indexing technique can be explained like this:
data(startIndex:step:endIndex)
If data has more dimensions than you used for indexing, this will assume : for every dimension after that.
To sum up my question:
data=reshape(1:24,2,3,4)
data(:,:,1) =
1 3 5
2 4 6
data(:,:,2) =
7 9 11
8 10 12
data(:,:,3) =
13 15 17
14 16 18
data(:,:,4) =
19 21 23
20 22 24
Using this example you can know what Matlab doing:
data(:,1)
ans =
1
2
data(:,12)
ans =
23
24
data(:,[1,12])
ans =
1 23
2 24
data(:,5:4:end)
ans =
9 17
10 18
If you use data(:,13),it throws an error.
What is the fastest and the simplest way to generate an array like
[0, 1, 3, 4, 6, 7, 9, 10, ...]
in MATLAB?
You can obtain the cumulative sum of the vector of steps (in your case it is [1 2 1 2 1 2 1 2 ...]). For example:
x = cumsum([0, repmat([1 2], 1, 4)])
x =
0 1 3 4 6 7 9 10 12
You can generate matrix with two rows: top row for odd array elements, bottom row for even elements. Than transform matrix into array with reshape.
>> a=[0:3:15; 1:3:16]
a =
0 3 6 9 12 15
1 4 7 10 13 16
>> a=reshape(a,1,12)
a =
0 1 3 4 6 7 9 10 12 13 15 16
Not one line but will work for either an odd or even number of total elements, and could be expanded if you wanted more than two different steps:
a = zeros(1,8);
a(1:2:end) = 0:3:10;
a(2:2:end) = 1:3:10;
Here is a simple and compact way:
A = 0:20;
A(3:3:end) = []
I have a large dataset that I need to divide randomly into 5 almost equal sized sets for cross validation. I have happily used _crossvalind_ to divide into sets before, however this time I need to divide chunks of data into these groups at a time.
Let's say my data looks like this:
data = [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18];
Then I want to divide them randomly into 5 groups in chunks of 2, e.g. like this
g1 = [3 4], [11 12]
g2 = [9 10]
g3 = [1 2], [15 16]
g4 = [7 8], [17 18]
g5 = [5 6], [13 14]
I think I can do this with some for-loops, but I'm guessing there must be a much more cost-efficient way to do it in matlab :-)
Any suggestions?
I'm interpreting your needs to be random ordering of sets, but within each set, the ordering of elements is unchanged from the parent set. You can use randperm to randomly order the number of sets and use linear indexing for the elements.
dataElements=numel(data);%# get number of elements
totalGroups=5;
groupSize=dataElements/totalGroups;%# I'm assuming here that it's neatly divisible as in your example
randOrder=randperm(totalGroups);%# randomly order of numbers from 1 till totalGroups
g=reshape(data,groupSize,totalGroups)'; %'# SO formatting
g=g(randOrder,:);
The different rows of g give you the different groupings.
You can shuffle the array (randperm) and then divide it into consequentive equal parts.
data = [10 20 30 40 50 60 70 80 90 100 110 120 130 140 150];
permuted = data(randperm(length(data)));
% padding may be required if the length of data is not divisible by the size of chunks
k = 5;
g = reshape(permuted, k, length(data)/k);