How to convert a character matrix into cell array? - arrays

I have 64 characters in a 4*4 matrix.I need to convert it into a cell array such that cell has 4 characters.For eg
Consider A=[TCTGCTCTCGGTTATATACACTGCCCAGAACACGTCAACAAGGCCAGTGTATCCTTCTTTGTGT]
i need to get a cell array as below
B={[TCTG][CTCT][CGGT][TATA]
[TACA][CTGC][CCAG][AACA]
[CGTC][AACA][AGGC][CAGT]
[GTAT][CCTT][CTTT][GTGT]}
i tried using the mat2cell function but im not able to understand it.please help.

Using a for-loop:
clc
clear
A = 'TCTGCTCTCGGTTATATACACTGCCCAGAACACGTCAACAAGGCCAGTGTATCCTTCTTTGTGT';
B = cell(4,4);
currentIdx = 0; % Use index to increment by steps of 4 when going through A
for k = 1:16
B{k} = A(currentIdx+1:currentIdx+4);
currentIdx = currentIdx+4;
end
B = B'
B =
'TCTG' 'CTCT' 'CGGT' 'TATA'
'TACA' 'CTGC' 'CCAG' 'AACA'
'CGTC' 'AACA' 'AGGC' 'CAGT'
'GTAT' 'CCTT' 'CTTT' 'GTGT'

You are starting with a 1xN matrix and want to convert it to a 1xN/4 cell array of 1x4 matrices. Your command should then be:
N = length(A);
M = 4;
B = mat2cell(A,1,ones(1,N/M)*M);
The first dimension is the 1, the second dimension is a string of 4's the size of the output cell array. The result:
B =
Columns 1 through 12
'TCTG' 'CTCT' 'CGGT' 'TATA' 'TACA' 'CTGC' 'CCAG' 'AACA' 'CGTC' 'AACA' 'AGGC' 'CAGT'
Columns 13 through 16
'GTAT' 'CCTT' 'CTTT' 'GTGT'

You can use method vec2mat that breaks your input vector to matrix
M = vec2mat(A, numberOfColumns)
(In your case numberOfColumns would be 16) and then use mat2cell. In your case, it would be:
C = mat2cell(M, [1,1,1,1], [4,4,4,4])
It means that all cels will have one row and 4 columns).
Effect of function c = mat2cell(x, [10, 20, 30], [25, 25]) would be:
The image shows why you have to convert vector to matrix. (example from matlab documentation)

You can also (ab)use the very versatile accumarray for this task:
A = 'TCTGCTCTCGGTTATATACACTGCCCAGAACACGTCAACAAGGCCAGTGTATCCTTCTTTGTGT';
n = 4;
B = accumarray(ceil(1/n:1/n:numel(A)/n).', A(:), [], #(x) {x.'}).'

Related

How to convert matrix to cell array

I have matrix A = 50x2
How to convert the data into cell array.
Should be I have 10 cell which each cell contain data [5x2].
Thank you for help.
That is what mat2cell does:
A = rand(50,2); % example matrix
N = 10; % number of cells in which to split the first dimension
result = mat2cell(A, repmat(size(A,1)/N, 1, N), size(A,2));
One can use num2cell:
N_ROWS = 5; N_COLS = 2;
A = rand(50,2);
B = num2cell(reshape(A,N_ROWS,N_COLS,[]),[1,2]); % B is 1x1x10 cell array
What this does is turn your input array into 5x2 "slices" stacked along the 3rd dimension.
You can add a squeeze(B), B = B(:) or a reshape(B,[],1) at the end if you need the output as a column vector.

Select entries from matrices according to indices in another matrix in MATLAB

I have matrices:
a= 0.8147 0.1270 0.6324
0.9058 0.9134 0.0975
b= 0.2785 0.9649 0.9572
0.5469 0.1576 0.4854
0.9575 0.9706 0.8003
c = 0.1419 0.7922
0.4218 0.9595
0.9157 0.6557
and also I have another matrix
I= 1 3 1 1
2 1 3 2
I want to get d matrix such that
d= a(1,3) b(3,1) c(1,1)
a(2,1) b(1,3) c(3,2)
where indices come as two consecutive entries of I matrix.
This is one example I get. However, I get different size matrices for a,b,c,.. and I.
Added: I is m x (n+3) which includes indices, and other (n+2) matrices which have corresponding entries are X,A1,A2,...,An,Y. When n is given, A1,A2,...,An matrices are generated.
Can someone please help me to write Matlab code for this task?
You can do it with varargin. Assuming that your matrices are constructed such that you can form your desired output in the way you want (Updated according to Carmine's answer):
function out = IDcombiner(I, varargin)
out = zeros(size(I, 1), nargin-1);
idx = #(m, I, ii) (sub2ind(size(m), I(:, ii), I(:, ii+1)));
for ii = 1:1:nargin-1
out(:, ii) = varargin{ii}(idx(varargin{ii}, I, ii));
end
Now using this function you can make your selection on a flexible number of inputs:
out = IDcombiner(I, a, b, c)
out =
0.6324 0.9575 0.1419
0.9058 0.9572 0.6557
There is also a one-liner solution, which I do not recommend, since it dramatically decreases the readability of the code and doesn't help you gain much:
IDcombiner = #(I,varargin) ...
cell2mat(arrayfun(#(x) varargin{x}(sub2ind(size(varargin{x}), ...
I(:,x), I(:,x+1))), 1:nargin-1, 'UniformOutput', false));
Normally a matrix is not interpreted as a list of indices, but you can have this if you use sub2ind. To use it you need the size of the matrix you are addressing. Let's make an example starting with a:
a(sub2ind(size(a), I(:,1), I(:,2)))
The code does not change if you first assign the newly generated matrices to a variable name.
will use the column I(:,1) as rows and I(:,2) as columns.
To make the code more readable you can define an anonymous function that does this, let's call it idx:
idx = #(m,I,i)(sub2ind(size(m), I(:,i), I(:,i+1)))
So finally the code will be
d = [a(idx(a,I,1)), b(idx(b,I,2)), c(idx(c,I,3))]
The code does not change if you first assign the newly generated matrices to a variable name.
Other details
Let's make an example with 2 central matrices:
a = rand(3,1) % 3 rows, 1 column
b = rand(3,3) % 3 rows, 3 columns
c = rand(3,3) % another squared matrix
d = rand(3,1) % 3 rows, 1 column
The definition of the anonymous function is the same, you just change the definition of the output vector:
output = [a(idx(a,I,1)), b(idx(b,I,2)), c(idx(c,I,3)), d(idx(d,I,3))]
Keep in mind that following that pattern you always need a I matrix with (n_matrices + 1) columns.
Generalization
Let's generalize this code for a number n of central matrices of size rxr and for "side matrices" of size rxc. I will use some values of those parameters for this example, but you can use what you want.
Let me generate an example to use:
r = 3;
c = 4;
n = 3;
a = rand(r,c); % 2D array
b = rand(r,r,n); % 3D array, along z = 1:n you have 2D matrices of size rxr
c = rand(r,c);
I = [1 3 1 2 1 3; 2 1 3 1 1 1];
The code I wrote can easily be extended using cat to append matrices (note the 2 in the function tells MATLAB to append on the direction of the columns) and a for cycle:
idx = #(m,I,i)(sub2ind(size(m), I(:,i), I(:,i+1)))
d = a(idx(a,I,1));
for i = 1:n
temp = b(:,:,i);
d = cat(2,d,temp(idx(tmp,I,i+1)));
end
d = cat(2,d,c(idx(c,I,n+1)));
If you really don't want to address anything "by hand", you can use cell arrays to put all the matrices together and then cyclically apply the anonymous function to each matrix in the cell array.

reshape 2d array to 3d array in matlab /octave

How can I reshape a 2d array to a 3d array with the last column being used as pages?
All data found in array2d should be in pages
example:
array2d=[7,.5,12; ...
1,1,1; ...
1,1,1; ...
4,2,4; ...
2,2,2; ...
2,2,2; ...
3,3,3; ...
3,3,3; ...
3,3,3];
The first page in the array would be
7,.5,12;
1,1,1;
1,1,1;
The second page in the array would be
4,2,4;
2,2,2;
2,2,2;
The third page in the array would be
3,3,3;
3,3,3;
3,3,3;
This is a 9x3 array how can I get it to be a 9x3x? (not sure what this number should be so I placed a question mark as a place holder) multidimensional array?
What I'm trying to get is to have
All the ones would be on one dimension/page all the two's would be another dimension/page etc... –
I tried reshape(array2d,[9,3,1]) and it's still a 9x3
Use permute with reshape -
N = 3; %// Cut after every N rows to form a "new page"
array3d = permute(reshape(array2d,N,size(array2d,1)/N,[]),[1 3 2]) %// output
Assuming that each slice of your matrix is the same in dimensions, we can do this very easily. Let's call the number of rows and columns that each slice would have to be M and N respectively. In your example, this would be M = 3 and N = 3. As such, assuming array2d is of the above form, we can do the following:
M = 3;
N = 3; %// This is also simply the total number of columns we have,
%// so you can do size(array2d, 2);
outMatrix = []; %// Make this empty. We will populate as we go.
%// Figure out how many slices we need
numRows = size(array2d,1) / M;
for k = 1 : numRows
%// Extract the k'th slice
%// Reshape so that it has the proper dimensions
%// of one slice
sliceK = reshape(array2d(array2d == k), M, N);
%// Concatenate in the third dimension
outMatrix = cat(3,outMatrix,sliceK);
end
With your example, we thus get:
>> outMatrix
outMatrix(:,:,1) =
1 1 1
1 1 1
1 1 1
outMatrix(:,:,2) =
2 2 2
2 2 2
2 2 2
outMatrix(:,:,3) =
3 3 3
3 3 3
3 3 3
This method should generalize for any number of rows and columns for each slice, provided that each slice shares the same dimensions.
Your array is already of size 1 in the 3rd dimension (in other words, it is already 9x3x1, to prove this try entering array2d(1,1,1)). If you want to concatenate 2d matrices along the 3rd dimension you can use cat.
For example:
a = [1,2;3,4];
b = [5,6;7,8];
c = cat(3,a,b);
c will be a 2x2x2 matrix.
This piece of code is specific for this example, I hope you will be able to understand how to go for other data samples.
out2 = [];
col = size(array2d,2);
for i = 1:3
temp2 = reshape(array2d(array2d == i),[],col);
out2 = cat(3,out2,temp2);
end

matlab maximum of array with unknown dimension

I would like to compute the maximum and, more importantly, its coordinates of an N-by-N...by-N array, without specifying its dimensions.
For example, let's take:
A = [2 3];
B = [2 3; 3 4];
The function (lets call it MAXI) should return the following values for matrix A:
[fmax, coor] = MAXI(A)
fmax =
3
coor =
2
and for matrix B:
[fmax, coor] = MAXI(B)
fmax =
4
coor=
2 2
The main problem is not to develop a code that works for one class in particular, but to develop a code that as quickly as possible works for any input (with higher dimensions).
To find the absolute maximum, you'll have to convert your input matrix into a column vector first and find the linear index of the greatest element, and then convert it to the coordinates with ind2sub. This can be a little bit tricky though, because ind2sub requires specifying a known number of output variables. For that purpose we can employ cell arrays and comma-separated lists, like so:
[fmax, coor] = max(A(:));
if ismatrix(A)
C = cell(1:ndims(A));
[C{:}] = ind2sub(size(A), coor);
coor = cell2mat(C);
end
EDIT: I've added an additional if statement that checks if the input is a matrix or a vector, and in case of the latter it returns the linear index itself as is.
In a function, it looks like so:
function [fmax, coor] = maxi(x)
[fmax, coor] = max(A(:));
if ismatrix(A)
C = cell(1:ndims(A));
[C{:}] = ind2sub(size(A), coor);
coor = cell2mat(C);
end
Example
A = [2 3; 3 4];
[fmax, coor] = maxi(A)
fmax =
4
coor =
2 2

indexing into an octave array using another array

Hi I have an three dimensional octave array A of size [x y z]
Now I have another array B of dimensions n * 3
say B(0) gives [3 3 1]
I need to access that location in A ie A(3, 3, 1) = say 15
something like A(B(0))
How do I go about it?
See the help for sub2ind (and ind2sub).
However, nowadays people recommend to use loops.
Well, first, B(0) is invalid index, as addressing in MATLAB and Octave begins from 1. Other issue is that you want that B(0) would contain a vector [3 3 1 ]. Matrices in MATLAB can not contain other matrices, only scalars. So you need to use a 3x3 cell array, a 3x3 struct or a 4-dimensional array. I'll choose here the cell array option, because I find it easiest and most convenient.
% Set random seed (used only for example data generation).
rng(123456789);
% Let's generate some pseudo-random example data.
A = rand(3,3,3);
A(:,:,1) =
0.5328 0.7136 0.8839
0.5341 0.2570 0.1549
0.5096 0.7527 0.6705
A(:,:,2) =
0.6434 0.8185 0.2308
0.7236 0.0979 0.0123
0.7487 0.0036 0.3535
A(:,:,3) =
0.1853 0.8994 0.9803
0.7928 0.3154 0.5421
0.6122 0.4067 0.2423
% Generate an example 3x3x3 cell array of indices, filled with pseudo-random 1x3 index vectors.
CellArrayOfIndicesB = cellfun(#(x) randi(3,1,3), num2cell(zeros(3,3,3)), 'UniformOutput', false);
% Example #1. Coordinates (1,2,3).
Dim1 = 1;
Dim2 = 2;
Dim3 = 3;
% The code to get the corresponding value of A directly.
ValueOfA = A(CellArrayOfIndicesB{Dim1,Dim2,Dim3}(1), CellArrayOfIndicesB{Dim1,Dim2,Dim3}(2), CellArrayOfIndicesB{Dim1,Dim2,Dim3}(3));
ValueOfA =
0.8839
% Let's confirm that by first checking where CellArrayOfIndicesB{1,2,3} points to.
CellArrayOfIndicesB{1,2,3}
ans =
[ 1 3 1 ]
% CellArrayOfIndicesB{1,2,3} points to A(1,3,1).
% So let's see what is the value of A(1,3,1).
A(1,3,1)
ans =
0.8839
% Example #2. Coordinates (3,1,2).
Dim1 = 3;
Dim2 = 1;
Dim3 = 2;
ValueOfA = A(CellArrayOfIndicesB{Dim1,Dim2,Dim3}(1), CellArrayOfIndicesB{Dim1,Dim2,Dim3}(2), CellArrayOfIndicesB{Dim1,Dim2,Dim3}(3));
ValueOfA =
0.4067
CellArrayOfIndicesB{3,1,2}
ans =
[ 3 2 3 ]
A(3,2,3)
ans =
0.4067

Resources