Say I have an Mx4 array A where the values in the first column are a number 1 to 12. Now I want to gather the rest of the columns in 12 separate Mx3 arrays depending on which number is in column 1.
How would I go about doing that?
You can use unique and splitapply as follows. The result is a cell array of arrays.
M = [2 11 41 51;
1 10 20 30;
1 62 83 22;
4 73 53 53;
2 84 94 14]; % example data
L = 5; % Group labels are 1:L (L=12 in your case)
[u,~,w] = unique(M(:,1));
result = cell(L,1);
result(u) = splitapply(#(x){x}, M(:,2:end), w);
This gives
>> celldisp(result)
result{1} =
10 20 30
62 83 22
result{2} =
11 41 51
84 94 14
result{3} =
[]
result{4} =
73 53 53
result{5} =
[]
Related
I have a 2D matrix with in the 1st dimension different channels, and in the 2nd dimension time samples. I want to rearrange this to a 3D matrix, with in the 1st and 2nd dimension channels, and in the 3rd time samples.
The channels have to mapped according to a certain mapping. Right now I am using a for-loop to do so, but what would be a no-loop solution?
N_samples = 1000;
N_channels = 64;
channel_mapping = reshape(1:64, [8 8]).';
% Results in mapping: (can also be random)
% 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
% 33 34 35 36 37 38 39 40
% 41 42 43 44 45 46 47 48
% 49 50 51 52 53 55 55 56
% 57 58 59 60 61 62 63 64
data = rand(N_channels, N_samples);
data_grid = NaN(8,8, N_samples);
for k = 1:N_samples
tmp = data(:, k);
data_grid(:, :, k) = tmp(channel_mapping);
end
You can do it in one go as follows:
data_grid = reshape(data(channel_mapping, :), 8, 8, []);
For example
I have one binary array with size of 9 as b = [0 1 0 1 0 1 1 1 1], Then another array 'm' with size of 7 as m = [21 28 36 45 45 66 66]. Here i want to change all the zeros of 'b' by 1st element of m then replace 1's of b by consecutive elements of 'm' so my output 1D array should be like k = [21 28 21 36 21 45 45 66 66].
Below is my code i really don't know where i did mistake please help me to solve this
b= [0 1 0 1 0 1 1 1 1];
b=b(:);
m = [21 28 36 45 45 66 66];
m = m(:);
k=zeros(size(b));
for i=1:length(b)
for j=2:length(m)
if b(i)==0
k(i)=m(1);
else
k(i)=m(j);
end
end
end
am getting output as
k = [21 66 21 66 21 66 66 66 66]
Use logical indexing instead - it is much faster and more readable:
b = [0 1 0 1 0 1 1 1 1];
m = [21 28 36 45 45 66 66];
k = zeros(size(b));
k(b==0) = m(1); % fill values where b=0 with m(1)
k(b==1) = m(2:sum(b)+1); % fill values where b=1 with consecutive m values
Result:
>> k
k =
21 28 21 36 21 45 45 66 66
I have an array with three columns like this:
A B C
10 75 20
30 67 50
85 12 30
98 49 70
I have A and B values, and I want to get the corresponding C value.
For example if I enter (30,67) it should display 50.
Does Matlab have any trick for getting C value?
(my dataset is very large, and I need a fast way)
you can use ismember:
ABC = [10 75 20
30 67 50
85 12 30
98 49 70];
q = [30 67
85 12];
[~, locb] = ismember( q, ABC(:,1:2), 'rows' );
C = ABC(locb,3);
The result you get is
C =
50
30
Note that the code assume all pairs in q can be found in ABC.
Let your input data be defined as
data = [ 10 75 20
30 67 50
85 12 30
98 49 70];
values = [ 30 67];
This should be pretty fast:
index = data(:,1)==values(1) & data(:,2)==values(2); %// logical index to matching rows
result = data(index,3); %// third-column value for those rows
This gives all third-column values that match, should there be more than one.
If you want to specify several pairs of values at once, and obtain all matching results:
index = any(bsxfun(#eq, data(:,1).', values(:,1)), 1) & ...
any(bsxfun(#eq, data(:,2).', values(:,2)), 1);
result = data(index,3);
For example, given
data = [ 10 75 20
30 67 50
85 12 30
98 49 70
30 67 80 ];
values = [ 30 67
98 49];
the result would be
result =
50
70
80
You can create a sparse matrix. This solution only works if C does not contain any zeros and A and B are integers larger 0
A = [10 30 85 98]';
B = [75 67 12 49]';
C = [20 50 30 70]';
S = sparse(A,B,C);
S(10,75) % returns corresponding C-Value if found, 0 otherwise.
Try accumarray:
YourMatrix = accumarray([A B],C,[],#mean,true);
This way YourMatrix will be a matrix of size [max(A) max(B)], with the values of C at YourMatrix(A(ind),B(ind)), with ind the desired index of A and B:
A = [10 30 85 98]';
B = [75 67 12 49]';
C = [20 50 30 70]';
YourMatrix = accumarray([A B],C,[],#mean,true);
ind = 2;
YourMatrix(A(ind),B(ind))
ans =
50
This way, when there is a repetition in A B, it will return the corresponding C value, provided each unique pair of A B has the same C value. The true flag makes accumarray output a sparse matrix as opposed to a full matrix.
I have an array in MATLAB
For example
a = 1:100;
I want to select the first 4 element in every successive 10 elements.
In this example I want to b will be
b = [1,2,3,4,11,12,13,14, ...]
can I do it without for loop?
I read in the internet that i can select the element for each step:
b = a(1:10:end);
but this is not working for me.
Can you help me?
With reshape
%// reshaping your matrix to nx10 so that it has successive 10 elements in each row
temp = reshape(a,10,[]).'; %//'
%// taking first 4 columns and reshaping them back to a row vector
b = reshape(temp(:,1:4).',1,[]); %//'
Sample Run for smaller size (although this works for your actual dimensions)
a = 1:20;
>> b
b =
1 2 3 4 11 12 13 14
To vectorize the operation you must generate the indices you wish to extract:
a = 1:100;
b = a(reshape(bsxfun(#plus,(1:4)',0:10:length(a)-1),[],1));
Let's break down how this works. First, the bsxfun function. This performs a function, here it is addition (#plus) on each element of a vector. Since you want elements 1:4 we make this one dimension and the other dimension increases by tens. this will lead a Nx4 matrix where N is the number of groups of 4 we wish to extract.
The reshape function simply vectorizes this matrix so that we can use it to index the vector a. To better understand this line, try taking a look at the output of each function.
Sample Output:
>> b = a(reshape(bsxfun(#plus,(1:4)',0:10:length(a)-1),[],1))
b =
Columns 1 through 19
1 2 3 4 11 12 13 14 21 22 23 24 31 32 33 34 41 42 43
Columns 20 through 38
44 51 52 53 54 61 62 63 64 71 72 73 74 81 82 83 84 91 92
Columns 39 through 40
93 94
I have an array for example: A=[01 255 03 122 85 107]; and I want to print the contents as
A=
FF 01
7A 03
6B 55
Basically a read out from a memory. Is there any function in MatLab lib? I need to do this with minimum use of loops.
Use this -
str2num(num2str(fliplr(reshape(A,2,[])'),'%1d'))
Output -
ans =
21
43
65
87
If you only want to print it as characters, use it without str2num, like this -
num2str(fliplr(reshape(A,2,[])'),'%1d')
Output -
ans =
21
43
65
87
General case with zeros padding -
A=[1 2 3 4 5 6 7 8 9 3] %// Input array
N = 3; %// groupings, i.e. 2 for pairs and so on
A = [A zeros(1,N-mod(numel(A),N))]; %// pad with zeros
out = str2num(num2str(fliplr(reshape(A,N,[])'),'%1d'))
Output -
out =
321
654
987
3
Edit for hex numbers :
Ar = A(flipud(reshape(1:numel(A),2,[])))
out1 = reshape(cellstr(dec2hex(Ar))',2,[])'
out2 = [char(out1(:,1)) repmat(' ',[numel(A)/2 1]) char(out1(:,2))]
Output -
out1 =
'FF' '01'
'7A' '03'
'6B' '55'
out2 =
FF 01
7A 03
6B 55