20 4 4 74 20 20 74 85 85 85
A = 36 1 1 11 36 36 11 66 66 66
77 1 1 15 77 77 15 11 11 11
3 4 2 6 7 8 10 10 15 17
how from the matrix A, I can extract the submatrix whose fourth line (end line) contains only the values [3 6 10]?
for a single value, I do:
B=A(:,A(4,:)==10)
but I do not know how to do this for several values.
Use ismember -
search_array = [3 6 10]
subA = A(:,ismember(A(end,:),search_array))
Or bsxfun -
subA = A(:,any(bsxfun(#eq,A(end,:),search_array(:)),1))
Related
Can this for-loop be vectorized?
I want to be able to vectorize the for-loop of this code to obtain a matrix like "sample". Trying to vectorize I got the "sample2" matrix, however as you can see it does not show the values I want for each row due to the linear index when I take "data" as a matrix instead of as a vector.
close all; clear all; clc;
N=5; n=10; n1=2; n2=8;
rand('state', sum(100*clock));
choose=round(((n-1)*rand(N,n))+1);
data=choose.^2;
idx=choose(:,n1:n2);
for i=1:N
dat=data(i,:);
sample(i,:)=dat(idx(i,:));
end
%Trying to vectorize to get the same result
sample2(:,(n1:n2)-n1+1)=data(idx);
Results:
data =
36 64 64 25 81 4 100 36 49 25
4 4 1 16 4 16 81 16 100 64
36 81 36 25 16 16 1 64 49 4
36 64 49 49 25 36 100 64 81 64
1 16 16 49 64 49 81 4 16 64
idx =
8 8 5 9 2 10 6
2 1 4 2 4 9 4
9 6 5 4 4 1 8
8 7 7 5 6 10 8
4 4 7 8 7 9 2
sample =
36 36 81 49 64 25 4
4 4 16 4 16 100 16
49 16 16 25 25 36 64
64 100 100 25 36 64 64
49 49 81 4 81 16 16
sample2 =
81 81 1 64 4 16 64
4 36 36 4 36 64 36
64 64 1 36 36 36 81
81 4 4 1 64 16 81
36 36 4 81 4 64 4
Looks like you are trying to index row major. But Octave indexes column major. You can transpose your input to get the indicies right. Also, if you want to index into the second col, you can just add the length of the first column.
Try this:
data2 = data';
sample2 = data2([idx + [0:size(idx,1)-1]'*size(data,2)])
First line just transposes the matrix so you get what would be row indexing of the original.
Second line modifies the index matrix to be total index instead of row index by adding the length of the original data rows, then references the data to provide the result.
This question already has answers here:
Collapsing matrix into columns
(8 answers)
Closed 6 years ago.
Let's say I have A = [1:8; 11:18; 21:28; 31:38; 41:48] Now I would like to move everything from column 4 onward to the row position. How do I achieve this?
A =
1 2 3 4 5 6 7 8
11 12 13 14 15 16 17 18
21 22 23 24 25 26 27 28
31 32 33 34 35 36 37 38
41 42 43 44 45 46 47 48
to
A2 =
1 2 3 4
11 12 13 14
21 22 23 24
31 32 33 34
41 42 43 44
5 6 7 8
15 16 17 18
35 36 37 38
45 46 47 48
reshape doesn't seem to do the trick
Here's a vectorized approach with reshape and permute -
reshape(permute(reshape(a,size(a,1),4,[]),[1,3,2]),[],4)
Making it generic, we could introduce the number of columns as a parameter. Hence, let ncols be that one. So, the solution becomes -
ncols = 4
reshape(permute(reshape(a,size(a,1),ncols,[]),[1,3,2]),[],ncols)
Sample run -
>> a
a =
20 79 18 82 27 23 59 66 46 21 48 95
96 83 46 49 34 88 23 42 17 27 15 54
11 88 34 92 23 62 86 56 32 32 91 54
>> reshape(permute(reshape(a,size(a,1),4,[]),[1,3,2]),[],4)
ans =
20 79 18 82
96 83 46 49
11 88 34 92
27 23 59 66
34 88 23 42
23 62 86 56
46 21 48 95
17 27 15 54
32 32 91 54
More info on the intuition behind such a General idea for nd to nd transformation, which even though originally was meant for NumPy/Python, extends to any programming paradigm in general.
Use Matrix indexing!
B=[A(:,1:4);A(:,5:8)]
In a loop...
for ii=0:floor(size(A,2)/4)-1
B([1+5*ii:5*(ii+1)],:)=A(:,[1+4*ii:4*(ii+1)] );
end
One more... perhaps unoptimized way would be to decompose the matrix into cells row-wise, transpose the cell array then concatenate everything back together:
B = cell2mat(mat2cell(A, size(A, 1), 4 * ones((size(A, 2) / 4), 1)).');
The above first uses mat2cell to decompose the matrix into non-overlapping cells. Each cell has the same number of rows as A but the total number of columns is 4 and there are exactly size(A, 2) / 4 of them. As such, we need to indicate a vector of ones where each element is 4 and there are size(A, 2) / 4 of these to tell us the number of columns for each cell. This creates a row-wise cell array and so we transpose this cell array and merge all of the cells together into one final matrix with cell2mat.
I have a 100x200 matrix and I would like to show this matrix as a density plot. Here is a 8x10 sample.
X = [104 122 138 159 149 167 184 164 190 158; ...
54 42 55 55 63 75 72 73 66 76; ...
15 22 28 21 23 28 32 47 32 40; ...
18 12 20 22 28 17 30 17 22 18; ...
10 7 14 10 14 11 14 20 16 10; ...
5 6 3 3 6 12 6 2 8 9; ...
4 8 9 2 5 3 3 12 7 7; ...
6 6 2 3 10 1 9 8 11 8]
I have tried to use functions like bar3, surf, hist and so on but they don't have the end result I am after.
I would also like to represent the y axis on the new successful plot to be on a log axis. So similar to having semilogy(x,y,'rx') for example.
Are there any other methods I could use?
How about "surf" it like a spectrogram?
XX = log([104 122 138 159 149 167 184 164 190 158;
54 42 55 55 63 75 72 73 66 76;
15 22 28 21 23 28 32 47 32 40;
18 12 20 22 28 17 30 17 22 18;
10 7 14 10 14 11 14 20 16 10;
5 6 3 3 6 12 6 2 8 9;
4 8 9 2 5 3 3 12 7 7;
6 6 2 3 10 1 9 8 11 8]
figure
surf(XX, 'edgecolor', 'none'); view(0,90); axis tight;
xlabel ('x')
ylabel ('y')
NOTE:The first row represent the first row (104,122,138...)
and row 8 represent row 8 (6,7,2....)
Dark red = high value
light blue = low value
Matlab also provides a heatmap function.
>> X = [104 122 138 159 149 167 184 164 190 158; ...
54 42 55 55 63 75 72 73 66 76; ...
15 22 28 21 23 28 32 47 32 40; ...
18 12 20 22 28 17 30 17 22 18; ...
10 7 14 10 14 11 14 20 16 10; ...
5 6 3 3 6 12 6 2 8 9; ...
4 8 9 2 5 3 3 12 7 7; ...
6 6 2 3 10 1 9 8 11 8];
>> heatmap(X)
ans =
HeatmapChart with properties:
ColorData: [8×10 double]
Show all properties
The following plot appears:
20 4 4 74 20 20 74 85 85 85 2 1
A = 36 1 1 11 36 36 11 66 66 66 4 1
77 1 1 15 77 77 15 11 11 11 1 4
3 4 2 6 7 8 10 10 15 17 1 5
20 4 85
B = 36 1 66
77 1 11
How from the matrix A, I can extract the submatrix whose coloumns contains the vectors B(:,i): [20 36 77] , [4 1 1] and [85 66 11]?
The desired result:
20 4 4 20 20 85 85 85
36 1 1 36 36 66 66 66
77 1 1 77 77 11 11 11
3 4 2 7 8 10 15 17
Now that you've explained what you want, transpose the matrices, select only the three top rows of A, and then use the third argument of ismember to specify that you want to compare entire rows:
A(:,ismember(A(1:3,:).', B.', 'rows').')
20 4 4 20 20 85 85 85
36 1 1 36 36 66 66 66
77 1 1 77 77 11 11 11
3 4 2 7 8 10 15 17
I have a 35x2 matrix (randomwords); and I have randomly selected 8 rows (rndm). What I need to do is remove the 8 selected rows from the randomwords matrix and save this new 27x2 matrix under a new variable heading, but I am finding this extremely difficult. I have provided my code Any help would be greatly appreciated.
target = words ([30 1 46 14 44 55 8 3 57 65 69 70 57 39 21 60 22 20 16 10 9 17 62 19 25 41 49 53 36 6 42 58 40 56 63]);
synonym = words([43 15 32 28 72 27 48 51 13 67 59 33 35 47 52 61 71 7 23 12 2 66 11 37 4 45 64 38 34 31 29 18 50 68 26]);
% assigns these elements of words into targets and synonyms. They are
% ordered so that words and synonyms are corresponding elements of
% synonyms and targets
% TO SELECT 8 RANDOM WORDS FOR THE ENCODING PHASE
randomwords = [target; synonym]'; % should be a 35x2 matrix
rndm = datasample(randomwords, 8, 1); % should select 8 random couples from the rows and none of them will be repeats
unpaired = rndm(:,2); % should select only the synonyms to form the unpaired stimuli; will be different for each run
Store the index of the removed rows in a variable, let's say removedrows and then just do:
result = randomwords;
result(removedrows,:) = [];