Add string headers to double columns Matlab - matlab

I have a double matrix A of size 10x10. What I want to do is I have a string array of size 1x10. I want to replace the first row in matrix A with this array of strings to be the headers of these columns. Same with the first column. If anyone could please advise how this can be done in Matlab.

For MATLAB R2013b or higher
If you have at least MATLAB R2013b or higher, you can use the array2table function to present the values in your desired format. Let's assume that your matrix is stored in A. Next, assuming your row headers are in a cell array and stored in row and your column headers are stored in a cell array called col, try this:
Try this:
T = array2table(A, 'RowNames', row, 'VariableNames', col);
Here's an example:
>> A = [1 12 30.48; 2 24 60.96; 3 36 91.44]
>> col = {'Feet', 'Inches', 'Centimeters'};
>> row = {'Number 1', 'Number 2', 'Number 3'};
>> T = array2table(A, 'RowNames', row, 'VariableNames', col)
T =
Feet Inches Centimeters
____ ______ ___________
Number 1 1 12 30.48
Number 2 2 24 60.96
Number 3 3 36 91.44
For MATLAB R2013a or lower
If you have R2013a or lower, you have no choice but to use a cell array for this. You can only achieve mixed data types in a matrix with a cell array. What you'll need to do is convert each number into an individual cell in a cell array. I'm going to introduce you to an undocumented function: sprintfc. You are able to print matrices directly to cell arrays.
Therefore, try doing this, assuming that row contains your strings in a cell array for the row header of size 1 x N and col contains your strings in a cell array for the column header of size 1 x N. With your matrix A:
Acell = sprintfc('%f', A); %// Convert matrix to cells
out = [' ', row; col.', Acell]; %// Generate final matrix
out contains your desired matrix. Here's an example:
>> A = [1 12 30.48; 2 24 60.96; 3 36 91.44];
>> Acell = sprintfc('%f', A);
>> row = {'Feet', 'Inches', 'Centimeters'};
>> col = {'Number 1', 'Number 2', 'Number 3'};
>> out = [' ', row; col.', Acell]
out =
' ' 'Feet' 'Inches' 'Centimeters'
'Number 1' '1.000000' '12.000000' '30.480000'
'Number 2' '2.000000' '24.000000' '60.960000'
'Number 3' '3.000000' '36.000000' '91.440000'

Related

How do I split a very large matrix into submatrices based on the value in a column?

I have a 5 x 600,000 matrix. I've had an idea to group the data so I want to group this matrix into submatrices based on the values in column 4.
For values between 0 and 500, I want one matrix, for values between 501 and 1000 I want another, and for values between 1001 and 1500 I want another.
How can I do this?
I currently don't have any reliable material, I have seen some examples online but they only seem to feature 2 variables (i.e. with value 1 or 0 in a column and grouping the 1s and the 0s into 2 submatrices).
I think in Matlab-speak you mean you have an nxm matrix where n=600000, m=5, but if not you can change accordingly.
Is this what you were looking to do?
n=600000;
m=5;
thisCol =4;
values_range = {[0,500];[501,1000];[1001,1500]}; % cell array of vectors
myMatrix = zeros(n,m);
myMatrix(:,thisCol) = 1:600000; % to prove it works.
theseSubMatrices = cell(length(values_range),1); % cell array of matrices
for j=1:length(values_range)
thisLow= values_range{j}(1);
thisHigh= values_range{j}(2);
theseSubMatrices{j} = myMatrix(myMatrix(:,thisCol)>=thisLow & myMatrix(:,thisCol)<=thisHigh,:);
end
If you have some data
arr = rand( 6e5, 5 ); % 5 columns / 600,000 rows
arr(:,5) = arr(:,5) .* 1500; % for this example, get column 5 into range [0,1500]
Then you can use histcounts to "bin" the 5th column according to your edges.
edges = [0, 500, 1000, 1500]; % edges to split column 5 by
[~,~,iSubArr] = histcounts( arr(:,5), edges );
And generate a cell array with one element per sub array
nSubArr = numel(edges)-1; % number of bins / subarrays
subArrs = arrayfun( #(x) arr( iSubArr == x, : ), 1:nSubArr, 'uni', 0 ); % Get a matrix per bin
Output:
subArrs =
1×3 cell array
{200521×5 double} {199924×5 double} {199555×5 double}

Exporting blank values into a .txt file - MATLAB

I'm currently trying to export multiple matrices of unequal lengths into a delimited .txt file thus I have been padding the shorter matrices with 0's such that dlmwrite can use horzcat without error:
dlmwrite(filename{1},[a,b],'delimiter','\t')
However ideally I do not want the zeroes to appear in the .txt file itself - but rather the entries are left blank.
Currently the .txt file looks like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887 0
61825 0
62785 0
63942 0
65159 0
66304 0
67509 0
68683 0
69736 0
70782 0
But I want it to look like this:
55875 3.1043e+05
56807 3.3361e+05
57760 3.8235e+05
58823 4.2869e+05
59913 4.3349e+05
60887
61825
62785
63942
65159
66304
67509
68683
69736
70782
Is there anyway I can do this? Is there an alternative to dlmwrite which will mean I do not need to have matrices of equal lengths?
If a is always longer than b you could split vector a into two vectors of same length as vector b and the rest:
a = [1 2 3 4 5 6 7 8]';
b = [9 8 7 ]';
len = numel(b);
dlmwrite( 'foobar.txt', [a(1:len), b ], 'delimiter', '\t' );
dlmwrite( 'foobar.txt', a(len+1:end), 'delimiter', '\t', '-append');
You can read in the numeric data and convert to string and then add proper whitespaces to have the final output as string based cell array, which you can easily write into the output text file.
Stage 1: Get the cell of strings corresponding to the numeric data from column vector inputs a, b, c and so on -
%// Concatenate all arrays into a cell array with numeric data
A = [{a} {b} {c}] %// Edit this to add more columns
%// Create a "regular" 2D shaped cell array to store the cells from A
lens = cellfun('length',A)
max_lens = max(lens)
A_reg = cell(max_lens,numel(lens))
A_reg(:) = {''}
A_reg(bsxfun(#le,[1:max_lens]',lens)) = cellstr(num2str(vertcat(A{:}))) %//'
%// Create a char array that has string data from input arrays as strings
wsp = repmat({' '},max_lens,1) %// Create whitespace cell array
out_char = [];
for iter = 1:numel(A)
out_char = [out_char char(A_reg(:,iter)) char(wsp)]
end
out_cell = cellstr(out_char)
Stage 2: Now, that you have out_cell as the cell array that has the strings to be written to the text file, you have two options next for the writing operation itself.
Option 1 -
dlmwrite('results.txt',out_cell(:),'delimiter','')
Option 2 -
outfile = 'results.txt';
fid = fopen(outfile,'w');
for row = 1:numel(out_cell)
fprintf(fid,'%s\n',out_cell{row});
end
fclose(fid);

Reshape Matlab table

I have the following table
name = ['A' 'A' 'A' 'B' 'B' 'C' 'C' 'C' 'C' 'D' 'D' 'E' 'E' 'E']';
value = randn(14, 1);
T = table(name, value);
i,e.
T =
name value
____ _________
A 0.0015678
A -0.76226
A 0.98404
B -1.0942
B 0.71249
C 1.688
C 1.4001
C -0.9278
C -1.3725
D 0.11563
D 0.076776
E 1.0568
E 1.1972
E 0.29037
I want to transform it in the following way: take the first two cells in value corresponding to different values in name and put it in the 5x2 matrix. This matrix would have rows corresponding to different names A,B,C,D,E and columns corresponding to values, e.g. the first two rows are
0.0015678 -0.76226
-1.0942 0.71249
This can be done with accumarray using a custom function. The first step is to convert the name column of T into a numeric vector; and then accumarray can be applied.
This approach requires T being sorted according to column 1, because only in this case is accumarray guaranteed to preserve order (as indicated in its documentation). So if T may not be sorted (although it is in your example), sort it first using sortrows.
T = sortrows(T, 1); %// you can remove this line if T is guaranteed to be sorted
[~, ~, names] = unique(T(:,1)); %// names as a numeric vector
result = cell2mat(accumarray(names, T.value, [], #(x) {x([1 2]).'}));
First figure out where each name has values located in the table, then cycle through each name and place the first two values encountered for each name into individual cell arrays. Once you're done, reshape the matrix to 5 x 2 as you have said. As such, do something like this:
names = unique(T.name); %// 1
ind = arrayfun(#(x) find(T.name == x), names, 'uni', 0); %// 2
vals = cellfun(#(x) T.value(x(1:2)), ind, 'uni', 0); %// 3
m = [vals{:}].'; %// 4
Let's go through each line of code slowly.
Line #1
The first line finds all unique names through unique and we store them into names.
Line #2
The next line goes through all of the unique names and finds those locations / rows in the table that share that particular name. I use arrayfun and go through each name in names, find those rows that share the same name as one we are looking for, and place those row locations into individual cells; these are stored into ind. To find the locations of each valid name in our table, I use find and the locations are placed into a column vector. As such, we will have five column vectors where each column vector is placed into an individual cell. These column vectors will tell us which rows match a particular name located in your table.
Line #3
The next line uses cellfun to go through each of the cells in ind and extracts the first two row locations that share a particular name, indexes into the value field for your table to pull those two values, and these are placed as two-element vectors into individual cells for each name.
Line #4
The last line of code simply unrolls each two-element vector. The first two elements of each name get stored into columns. To get them into rows, I simply transpose the unrolling. The output matrix is stored into m.
If you want to see what the output looks like, this is what I get when I run the above code with your example table:
m =
0.0016 -0.7623
-1.0942 0.7125
1.6880 1.4001
0.1156 0.0768
1.0568 1.1972
Be advised that I only showed the first 5 digits of precision so there is some round-off at the end. However, this is only for display purposes and so what I got is equivalent to what your expect for the output.
Hope this helps!
If you want use the tables, you could try something like this:
count = 1;
U = unique(table2array(T(:,1)));
for ii = 1:size(U,1)
A = find(table2array(T(:,1)) == U(ii));
A = A(1:2);
B(count,1:2) = table2array(T(A,2));
count = count + 1;
end
Personally, I would find this simpler to do with your name and value arrays and forget about the table. If it is a requirement then I understand, however I will provide my solution still. It may provide some insight either way.
count = 1;
U = unique(name);
for ii = 1:size(U,1)
A = find(name == U(ii));
A = A(1:2);
B(count,1:2) = value(A);
count = count + 1;
end
Quick and dirty, but hopefully it's good enough. Good luck.
Another solution that is more manageable and easily scalable exists. Since MATLAB R2013b you can use a specialized function for pivoting a table (which is what you want to do): unstack.
In order to get exactly what you wanted, you need to add an extra variable to your table that will indicate replications:
name = ['A' 'A' 'A' 'B' 'B' 'C' 'C' 'C' 'C' 'D' 'D' 'E' 'E' 'E']';
value = randn(14, 1);
rep = [1, 2, 3, 1, 2, 1, 2, 3, 4, 1, 2, 1, 2, 3];
T = table(name, value, rep);
T =
name value rep
____ _________ ___
A 0.53767 1
A 1.8339 2
A -2.2588 3
B 0.86217 1
B 0.31877 2
C -1.3077 1
C -0.43359 2
C 0.34262 3
C 3.5784 4
D 2.7694 1
D -1.3499 2
E 3.0349 1
E 0.7254 2
E -0.063055 3
Then you just use unstack like this:
pivotTable = unstack(T, 'value','name')
pivotTable =
rep A B C D E
___ _______ _______ ________ _______ _________
1 0.53767 0.86217 -1.3077 2.7694 3.0349
2 1.8339 0.31877 -0.43359 -1.3499 0.7254
3 -2.2588 NaN 0.34262 NaN -0.063055
4 NaN NaN 3.5784 NaN NaN
Afterwards, it's a matter of re-arranging the table if you still want to.
The easiest way is to first convert the table into a matrix form and then reshape it by using the "reshape" function in Matlab.
matrix = t{:,:};% t-- your table variable
reshape_matrix = reshape(matrix ,[2,3]) % [2,3]--> the size of the matrix you desire
These two steps can be done by one line of code
reshape_matrix = reshape(t{:,:},[2,3]);

How using reshape with cell arrays?

Unfortunately I have to work with a dataset of cell arrays, which don't even have the same input..
My dataset (the relevant columns of cell arrays) look as follows:
Data =
1 'd2'
1 'd3'
2 'u2'
2 'd2'
2 'u3'
3 'e2'
... ...
I want to reshape them in a way, that all inputs of the second column of all rows containing the same number in the first column, are stored in new columns. Because the single rows of each number in the first column aren't always the same (but at highest 4) I wrote following code:
% creating 4 new cell arrays for the new columns
cells = cell(length(Data(:,1)),4);
Data = [Data,cells];
% reshaping Data
Data(:,3:6) = reshape(Data(Data(:,1) == 1,2),1,[]);
Data(:,3:6) = reshape(Data(Data(:,1) == 2,2),1,[]);
This would perfectly work with matrices. But unfortunately, it doesn't work on cell arrays!
Please could you help me out, where I have to place the curly brackets, so it would work? I didn't get it so far and maybe I'm just overseeing it now! ;-)
Thank you a lot!
Personally I find a loop to be the most simple and flexible solution in this case:
mydata={1 'd2'
1 'd3'
2 'u2'
2 'd2'
2 'u3'
3 'e2'}
list = unique([mydata{:,1}])
result = {};
for t=1:numel(list)
count=0;
for u =1:size(mydata,1)
if mydata{u,1}==list(1,t)
count = count+1;
result(t,count)=mydata(u,2)
end
end
end
Note that a vectorized approach will likely be more efficient, but unless your data is big it should not matter much.
This could be one approach that uses the masking capability of bsxfun -
%// Input
Data = {
1 'd2'
1 'd3'
2 'u2'
2 'd2'
2 'u3'
3 'e2'}
%// Find the IDs and the unique IDs
ids = cell2mat(Data(:,1))
id_out = num2cell([1:max(ids)]') %//'# To be used as the first col of desired o/p
%// Find the extents of each group/ID members
grp_extents = sum(bsxfun(#eq,[1:max(ids)],ids),1)
%// Or use accumarray which could be faster -
%// grp_extents = accumarray(ids,ones(1,numel(ids))).'
%// Get a cell array with the members (strings) from the second column of Data
%// put into specific columns based on their IDs
string_out = cell(max(grp_extents),numel(grp_extents))
string_out(bsxfun(#le,[1:max(grp_extents)]',grp_extents)) = Data(:,2) %//'# This is
%// where the masking is being used for logical indexing
%// Transpose the string cell array and horizontally concatenate with 1D
%// cell array containing the IDs to form the desired output
Data_out = [id_out string_out']
Output -
Data_out =
[1] 'd2' 'd3' []
[2] 'u2' 'd2' 'u3'
[3] 'e2' [] []

How to read N matrixes from the keyboard

I need to save N matrixes from the user. I already save the matrix asking for how many rows and columns and iterate N times, but my question is how can I save the name of the N matrix.
Example
matrix1 = [1 2 3; 4 5 6]
matrix2 = [7 8 9; 14 15 16]
.
.
.
matrixN = [0 0 0; 0 0 0]
This is the code I have:
for k = 1:nClases
for i = 1:m(i)
for j = 1:n(i)
str = ['Ingresa elemento en fila ' num2str(i) ', columna ' num2str(j) ' de clase' num2str(k) ': ' ];
clase(i,j) = input(str);
eval(sprintf('clase%d = [1:k]', k));
end
end
end
k is the number of matrix I need.
m is the rows.
n is the columns.
I am assuming you want the user to input N matrices and don't know how to save the matrices with a given name.
You can try the following:
After a given matrix is filled out, you can do:
Matrix{k} = clase;
This will come after the i and j loops end.
At the end, you will have a cell array of matrices. To access the second one, you can just type Matrix{2}
It sounds like what you are trying to do is create a variable name for each incrementing matrix, matrix_k. The following line will return a string "filename" with the string "matrix" followed by the matrix number k:
filename = genvarname(['matrix' num2str(k)]);
You can then save the matrix with the following:
save(filename, 'matrix');
If you would like to simply assign the value of each new matrix to a new variable name, you could instead use the following:
eval(['matrix' num2str(k) '=' num2str(matrix)])
which will create a variable "matrix_k" and assign the current value of matrix to it.