how to group elements in matrix in matlab? - matlab

For eg. I have [1;1;0;0;1;0;0;0;1;1;1;0] this as column and I want output the group of four elements:
1100
1000
1110
How to do this? I tried it with accumarray() but it is not working.

Assuming your vector only contains the elements 0 and 1 and has n*4 elements:
bvec = [1;1;0;0;1;0;0;0;1;1;1;0];
bvec = char(reshape( bvec, 4, numel(bvec)/4 ) + '0').';
Let's break it down:
reshape( bvec, numel(bvec)/4, 4 );
breaks your column vector (could be row vector as well) into a matrix that has 4 rows (your 4 bit[?] groups), it is a 4*n matrix of type double,
+ '0' adds a numerical value of 48 to represent the ASCII character '0'; this translates all values of 0 to 48 (ASCII '0') and all values of 1 to 49 (ASCII '1')
char( ... ) converts your matrix to a character type matrix.
.' transposes the matrix in the very end to get a n*4 matrix.
Result:
bvec =
1100
1000
1110

how is this?
A = [1;1;0;0;1;0;0;0;1;1;1;0];
B = reshape(A,4,3)'; %//DONT FORGET THE `'` or your results would be wrong...
C = strcat(num2str(B)); %C is a char Array currently
C =
1 1 0 0
1 0 0 0
1 1 1 0
Remove the space:
you can do C(:,2:3) =[];C(:,3:4)=[];C(:,4:5)=[]; to create a 3 x 4 char Array:
C =
1100
1000
1110
but why would you right? So the better way is:
regexprep(cellstr(C),'[^\w'']',''); %//Now a cell Array. It is generally better practice to store strings as Cell Array instead of Char Array.
ans =
'1100'
'1000'
'1110'

Related

Find values in a table with multiple data types and set them to NA or NaN

I have a table (which I've called 'T' in this question) that is approx 105 x 10, with columns 2 & 3 containing strings, and all the rest containing numbers.
In columns 5 through 10 (which only contain numbers), I have some values of 999 interspersed in the data that I want to set to NA or NaN.
How can I do this?
I've tried:
idx = T{:,5:10} == 999;
T{idx} = NaN;
T(ismissing(T,{999})) = NaN;
T{T==999}=NaN;
T(T{:,5:10}==999,:) = NaN;
The table data looks like this:
1 'LevelTwo' 'Trial1' 0 -0.354977112125573 -0.342962246562734 999 999 999 999
1 'LevelTwo' 'Trial1' 1 -0.185281358489472 0.196843601863376 0.191455534789190 0.191455534789190 0.196337466839364 0.239420563280515
1 'LevelTwo' 'Trial1' 1 0.393217912708115 0.301686005068917 -0.167798347008035 -0.167798347008035 -0.107991484625157 0.108461970332887
1 'LevelTwo' 'Trial1' 1 -0.145362442084958 -0.327523065746791 0.184717880799754 0.184717880799754 0.0848972787264908 0.166202231586311
1 'LevelTwo' 'Trial2' 1 -0.309966518338289 -1.67389513513988 0.186656639405178 0.186656639405178 -0.0898354852721748 -0.232764706067819
1 'LevelTwo' 'Trial2' 1 -0.0677751233445754 0.131643384129556 0.320810761759298 0.320810761759298 0.244546397660921 0.277629762491316
1 'LevelTwo' 'Trial2' 1 -0.180564795679273 0.101929692518556 -0.134486855393823 -0.134486855393823 -1.61383942825616 0.100825254423938
1 'LevelTwo' 'Trial3' 0 999 999 999 999 999 999
1 'LevelTwo' 'Trial3' 1 -0.281085702707834 -0.0950243910429598 -0.0856708961622575 -0.0856708961622575 -0.221969474699963 -0.158533022159099
1 'LevelTwo' 'Trial4' 1 -1.01621209202249 -1.05630974785680 -0.128439670451306 -0.128439670451306 0.216852995526501 0.154914119245274
10 'LevelTwo' 'Trial10' 0 -2.60256948228157 -2.21021399689544 -0.513562238953105 -0.513562238953105 -0.918985308726539 -1.11565199530760
10 'LevelTwo' 'Trial11' 0 0.638560227147980 -0.660529540036614 -0.0354971842584826 -0.0354971842584826 999 999
Your problem is that you have a matrix of logical indices which you want to use to index into a matrix-like section of your table. However the only logical indexing supported by tables is vectors of logical indices referencing which rows or columns to pick. A logical vector on the row side of the index chooses the rows that are referenced for all referenced columns, and vice versa. It has to be this way because of the ambiguity that would arise from possible mixed data types that could be referenced by each element of the index.
You can stick with logical indexing if you work with the subset of the table that is numeric as a separate numeric array:
numbers = T{:,5:10};
numbers(numbers == 999) = NaN;
T{:,5:10} = numbers;
Or you can work column by column to deal in the table directly, with one logical vector to index rows at a time:
for ii = 5:10
T{T{:,ii} == 999,ii} = NaN;
end
The following line of code does exactly what I need.
standardizeMissing(T,999)

aggregating matrix and cell array

I am aggregating 3x3 matrix D to 2x2 (adding column/row 1 and 2 together). Names for the rows and columns of matrix D are kept in 1x3 vector m.
And I am looking for a way to aggregate vector M by removing one of elements so it has the size 2x1.
Given 3x3 matrix D:
D =
1 2 3
4 5 6
7 8 9
And 2x3 aggregation matrix S:
S =
1 1 0
0 0 1
I aggregate D into 2x2 matrix by:
D = S*D*S'
D =
12 15
9 9
And the names for the columns and rows are stored in 3x1 vector m.
m =
'A'
'B'
'C'
I want to remove element 2 ('B') so the final output looks like this:
m =
'A'
'C'
Any suggestions ?
I assumed that you want to find the top left corners of blocks of a block-diagonal matrix and return their column indexes.
For example for the following matrix:
11100 10000
11100 00000
00010 => 00010
00010 00000
00001 00001
The result will be [1 4 5].
S = [1 1 0
0 0 1];
m = {'A';'B';'C'};
sz = size(S);
h = diff([zeros(sz(1),1),S],1,2)>0;
v = diff([zeros(1,sz(2));S],1,1)>0;
[~,idx]=find(h&v);
result = m(idx)

matlab: how to compare two matrices to get the indeces of the elements that differs from one to another

I'm using Matlab with very big multidimensional similar matrices and I'd like to find the differences of between them.
The two matrices have the same size.
Here is an example:
A(:,:,1) =
1 1 1
1 1 1
1 1 1
A(:,:,2) =
1 1 1
1 1 1
1 1 1
A(:,:,3) =
1 1 1
1 1 1
1 1 1
B(:,:,1) =
1 1 99
1 1 99
1 1 1
B(:,:,2) =
1 1 1
1 1 1
1 1 1
B(:,:,3) =
1 1 99
1 1 1
1 1 1
I need a function that give me the indeces of the values that differs, in this example this would be :
output =
1 3 1
1 3 3
2 3 1
I know that I can use functions like find(B~=A) or find(~ismember(B, A)) I don't know how to change their output to the indeces I want.
Thank you all!
You almost have it correct! Remember that find finds column major indices of where in your matrix (or vector) the Boolean condition you want to check for is being satisfied. If you want the actual row/column/slice locations, you need to use ind2sub. You would call it this way:
%// To reproduce your problem
A = ones(3,3,3);
B = ones(3,3,3);
B(7:8) = 99;
B(25) = 99;
%// This is what you call
[row,col,dim] = ind2sub(size(A), find(A ~= B));
The first parameter to ind2sub is the matrix size of where you're searching. Since the dimensions of A are equal to B, we can choose either A or B for the first input, and we use size to help us determine the size of the matrix. The second input are the column major indices that we want to access the matrix. These are simply the result of find.
row, col, and dim will give you the rows, columns and slices of which elements in your 3D matrix were not equal. Also note that these will be column vectors, as the output of find will produce a column vector of column-major indices. As such, we can concatenate each of the column vectors into a single matrix and display your information. Therefore:
locations = [row col dim];
disp(locations);
1 3 1
2 3 1
1 3 3
As such, the first column of this matrix tells you the row locations of where the matrix values are unequal, the second column of this matrix tells you the column locations of where the matrix values are unequal, and finally the third column tells you the slices of where the matrix values are unequal. Therefore, we have three points in this matrix that are unequal, which are located at (1,3,1), (2,3,1) and (1,3,3) respectively. Note that this is unsorted due to the nature of find as it searches amongst the columns of your matrix first. If you want to have this sorted like you have in your example output, use sortrows. If we do this, we get:
sortrows(locations)
ans =
1 3 1
1 3 3
2 3 1

convert string to binary matrix with 1 bit per column

How do I convert characters from a file, e.g. 'hello' to a binary matrix like this:
[1 1 0 1 1 0 0 0 1 0 .......]
where each column of the matrix has only a 1 bit value that is 0 or 1.
All I have done so far is converted the string into the matrix of binary where each column has 7 bits of binary.
Example: 'hello'
1 1 0 1 1 0 0 0 1 0
You need a combination of dec2bin and str2num:
First, convert your input into a binary representation:
WORD = 'hello';
WORD_BINARY = dec2bin(WORD,7) % The 7 gives the number of bits
This results in:
WORD_BINARY =
1101000
1100101
1101100
1101100
1101111
This is a string, which now has to be turned into a vector:
for i=1:size(WORD_BINARY,1)
for j=1:size(WORD_BINARY,2)
WORD_OUTPUT(1,(i-1)*size(WORD_BINARY,2)+j) = str2num(WORD_BINARY(i,j))
end
end
WORD_OUTPUT in this case is a <1x40> vector, starting with:
WORD_OUTPUT =
[ 1 1 0 1 0 ...
Edit
If you do not want two for loops, you can use reshape first (but be aware, that reshape orders by column, not row):
WORD = 'hello';
WORD_BINARY = reshape(dec2bin(WORD,7)',1,[]);
% note the <'> after the dec2bin, to transpose the matrix
for j=1:size(WORD_BINARY,2)
WORD_OUTPUT(1,j) = str2num(WORD_BINARY(1,j));
end

Output in Vector form

I am getting output of reshape function as follow
s1 =
11
00
10
11
01
11
10
10
10
10
10
10
10
01
10
01
How to convert s1 as
[1 1 0 0 1 0 1 1 0 1 1 1 1 0 1 0 1 0 1 0 1 0 1 0 1 0 0 1 1 0 0 1]
so i can pick up bit values
s1(1) will be 1
s1(3) will be 0
s1(5) will be 1
I have tried it with reshape and transpose but not picking up correct bit values. Appreciate any help..
I am doing following operation with below code
converting cipher text to bytes, then I am calculating index variable (called as p) & formula is MOD(No of Bytes,3).. I have ciphertext length as 5 bytes so Index Variable (p) is 2.. I will always have index varaible values as 0 or 1 or 2 which will be based on no. of Bytes
Say ciphertext is 11001011 01111010 10101010 10011001 01010101
This data is five bytes there for inde variable is 2
11001011 01111010 10101010 10011001 01010101
Now
for first two bits (11) , index variable to be assigned as 2
for next two bits (00), index variable to be assigned as 0
for next two bits (10), index variable to be assigned as 1
for next two bits (11), index variable to be assigned as 2..so on till end of my bits.
Other Example
Ciphertet with Three Bytes 11001011 01111010 10101010
Index Variable (p) will be 0
for first two bits (11) , index variable to be assigned as 0
for next two bits (00), index variable to be assigned as 1
for next two bits (10), index variable to be assigned as 2
for next two bits (11), index variable to be assigned as 0..
so on till end of my bits..
s = '11001011 01111010 10101010 10011001 01010101'
p = rem(numel(regexp(s,' [01]'))+1,3)
k = (0:2)'
s1 = reshape(regexprep(s,' ',''),2,[])'
n = size(s1,1)
N = k(:,ones(fix((n+1)/3)+1,1))
P = N(find(N(:,1) == p)+(0:n-1))'
Well s1' will give you
[11 00 10 11 ...]
but if you show us the input to your function I might be able to give you the answer you really want.
The key to this question is that the elements are of char type. Then you could use reshape like this:
reshape(s1.',1, [])
ans = 11001011...
This is a similar question.