Extracting x rows every n rows from a table in matlab - matlab

I want to create a new table extracting x rows every n rows from my table. For example if my table is:
1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
17 18
19 20
21 22
I want something like:
1 2
3 4
11 12
13 14
21 22

Here is an easy way by using ismember and mod to categorize the rows
n = 5;
x = 2;
b = a(logical(ismember(mod(0:size(a)-1,n),0:x-1)),:);
such that
>> b
b =
1 2
3 4
11 12
13 14
21 22
Data
a = [1 2
3 4
5 6
7 8
9 10
11 12
13 14
15 16
17 18
19 20
21 22];

Related

average using index form the array

I have and time sequence: lines are channels, columns are time points, say
x = [1 2 3 4 5 6 7 8; 9 10 11 12 13 14 15 16; 17 18 19 20 21 22 23 24 ; 25 26 27 28 29 30 31 32]
x =
1 2 3 4 5 6 7 8
9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32
I have an index of a specific points in time when I want to compute mean for the x
y = [4 5 6]
y =
4 5 6
How can I get a 3D array out of x with +- 2 points around and average thrue 3d dimation? In over words, I need to average
3 4 5 4 5 6 5 6 7
11 12 13 and 12 13 14 and 13 14 15
19 20 21 20 21 22 21 22 23
27 28 29 28 29 39 29 30 31
for each entrance.
Since the mean is of all the rows, just get the 3 chunks (1 before, the index, and 1 after) and calculate the mean value. I didn't use the mean function since will calculate the mean of each column. Instead of that, I just add the 3 chunks and divide them by 3.
% Get the x values
x = [1 2 3 4 5 6 7 8;...
9 10 11 12 13 14 15 16;...
17 18 19 20 21 22 23 24 ;...
25 26 27 28 29 30 31 32]
% Define the idx
idx = [4 5 6]
% Get the mean matrix. It is the mean of 1 column before
% the idx and 1 column after. Since there are 3, divided by 3.
% 1 before index 1 after
MeanMatrix = (x(:,idx-1)+x(:,idx)+x(:,idx+1))./3
The best approach i think would be to loop over the array something like this:
result = [];
for i = 1:length(y)
result = [result, mean(x(1:height(x),y(i)-1:y(i)+1), 'all')];
end
Here, we are just splitting it into the chunks you want using indexing then computing the mean over the entire selected chunk.

Convert 2D into 3D using reshape subject to conditions

I want to use reshape.
v=[1:20 ;2:2:40 ;3:3:60 ;4:4:80];
Using reshape(v,4,4,5) gives output:
ans(:,:,1) =
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
ans(:,:,2) =
17 2 10 18
18 4 12 20
19 6 14 22
20 8 16 24
And so on. But I desire
ans(:,:,1)=
1 2 3 4
2 4 6 8
3 6 9 12
4 8 12 16
ans(:,:,2)=
5 10 15 20
6 12 18 24
7 14 21 28
8 16 24 32
reshape(v',4,4,5) didn't work for me either
You are on the right track with the reshape function. You just need to transpose your 3D slices using permute. i.e.
permute(reshape(v,4,4,[]),[2 1 3])

how to display my vertical matrix in an horizontal matrix?

In one file 'file.mat', I have a matrix which its size is (1,100), it is written vertically like this:
M1 =
Columns 1 through 26:
6 13 3 15 13 12 8 5 5 1 11 8 5 9 1 7 15 9 2 5 7 7 3 9 0 13
Columns 27 through 52:
4 5 7 2 6 6 2 7 12 5 5 12 0 6 11 15 1 2 12 9 13 9 7 13 2 2
Columns 53 through 78:
7 15 4 15 5 12 5 12 14 3 10 15 12 5 5 15 3 3 9 3 6 0 13 13 8 5
Columns 79 through 100:
2 10 0 8 5 5 9 8 13 14 15 14 10 6 7 8 9 10 14 5 2 5
How to change it in an horizontal Matrix?
You can use M1.' or permute(M1,[2 1]). If you want all numbers to be in one horizontal line (i.e. to be an vector) you can use reshape(M1, [1,100])
What you have is a horizontal vector, but MATLAB displays it like that so that you can easily see where each element belongs. I guess what you want is to display the vector as a horizontal vector, so that you can copy-paste it. If so:
You can use sprintf if you want to display this as a long vector.
sprintf('%i ', M)
ans =
35 3 31 8 30 4 1 32 9 28 5 36 6 7 2 33 34 29 26 21 22 17 12 13 19 23 27 10 14 18 24 25 20 15 16 11
Or if you need the brackets:
['[', sprintf('%i ', M), ']']
ans =
[35 3 31 8 30 4 1 32 9 28 5 36 6 7 2 33 34 29 26 21 22 17 12 13 19 23 27 10 14 18 24 25 20 15 16 11 ]
You can also have it tab-separated: sprintf('%i\t', M), or with commas: sprintf('%i,', M).
If you want to reshape your horizontal vector to a vertical, you can do:
M = M.';
Note that ' is NOT the transpose operator, .' is. If you have a vector, but don't know whether it's horizontal of vertical, use the following notation: M = M(:).', or reshape(M, 1, []).

Accumulate sliding blocks into a matrix

In MATLAB, we can use im2col and col2im to transform from columns to blocks and back, for example
>> A = floor(30*rand(4,6))
A =
8 5 2 13 15 11
22 11 27 13 24 24
5 18 23 9 23 15
20 23 14 15 19 10
>> B = im2col(A,[2 2],'distinct')
B =
8 5 2 23 15 23
22 20 27 14 24 19
5 18 13 9 11 15
11 23 13 15 24 10
>> col2im(B,[2 2],[4,6],'distinct')
ans =
8 5 2 13 15 11
22 11 27 13 24 24
5 18 23 9 23 15
20 23 14 15 19 10
my question is that: after using im2col with sliding mode
>> B = im2col(A,[2 2],'sliding')
B =
8 22 5 5 11 18 2 27 23 13 13 9 15 24 23
22 5 20 11 18 23 27 23 14 13 9 15 24 23 19
5 11 18 2 27 23 13 13 9 15 24 23 11 24 15
11 18 23 27 23 14 13 9 15 24 23 19 24 15 10
I wish to get a 4-by-6 matrix C from B(without knowing A) that the value at each site equals the original value multiple the times of sampling.
In other word, C(1,1)=A(1,1), C(1,2)=A(1,2)*2, C(2,2) = A(2,2)*4
Though we can easily implement with a for-loop, but the efficiency is critically low. So how to vectorize the implementation?
If I'm understanding correctly, you're desired output is
C = [ 8 10 4 26 30 11
44 44 108 52 96 48
10 72 92 36 92 30
20 46 28 30 38 10 ]
which I got by computing C = A.*S where
S = [ 1 2 2 2 2 1
2 4 4 4 4 2
2 4 4 4 4 2
1 2 2 2 2 1 ]_
The entries in S represent how many sliding blocks each entry is a member of.
I believe your question boils down to how to construct the matrix S.
Solution:
S = min(min(1:M,M:-1:1),x)'*min(min(1:N,N:-1:1),y)
C = A.*S
where A is size M-by-N, and your sliding block is size x-by-y.
Explanation:
In the given example, M=4, N=6, x=2, and y=2.
Notice the solution S can be written as the outer product of two vectors:
S = [1;2;2;1] * [1,2,2,2,2,1]
We construct each of these two vectors using the values of M,N,x,y:
min(1:M,M:-1:1)' == min(1:4,4:-1:1)'
== min([1,2,3,4], [4,3,2,1])'
== [1,2,2,1]'
== [1;2;2;1]
In this case, the extra min(...,x) does nothing since all entries are already <=x.
min(1:N,N:-1:1) == min(1:6,6:-1:1)
== min([1,2,3,4,5,6],[6,5,4,3,2,1])
== [1,2,3,3,2,1]
This time the extra min(...,y) does matter.
min(min(1:N,N:-1:1),y) == min([1,2,3,3,2,1],y)
== min([1,2,3,3,2,1],2)
== [1,2,2,2,2,1]

MATLAB:To create segments of numeric values continously ordered

A simple MATLAB-problem:
coordinates=[1 6 ;9 20];
coordinates =
1 6
9 20
What i now want to have is:
idxList=[1 2 3 4 5 6 9 10 11 12 13 14 15 16 17 18 19 20];
idxList =
1 2 3 4 5 6 9 10 11 12 13 14 15 16 17 18 19 20
How i have to make that?
Here's one way:
>> cell2mat(cellfun(#(x) x(1):x(2), num2cell(coordinates, 2), 'UniformOutput', 0)')
ans =
1 2 3 4 5 6 9 10 11 12 13 14 15 16 17 18 19 20