Reading text values into matlab variables from ASCII files - matlab

Consider the following file
var1 var2 variable3
1 2 3
11 22 33
I would like to load the numbers into a matrix, and the column titles into a variable that would be equivalent to:
variable_names = char('var1', 'var2', 'variable3');
I don't mind to split the names and the numbers in two files, however preparing matlab code files and eval'ing them is not an option.
Note that there can be an arbitrary number of variables (columns)

I suggest importdata for operations like this:
d = importdata('filename.txt');
The return is a struct with the numerical fields in a member called 'data', and the column headers in a field called 'colheaders'.
Another useful interface for importing manipulating data like these is the 'dataset' class available in the Statistics Toolbox.

If the header is on the first row then
A = dlmread(filename,delimString,2,1);
will read the numeric data into the Matrix A.
You can then use
fid = fopen(filename)
headerString = fscanf(fid,'%s/n') % reads header data into a string
fclose(fid)
You can then use strtok to split the headerString into a cell array. Is one approach I can think of deal with an unknown number of columns
Edit
fixed fscanf function call

Just use textscan with different format specifiers.
fid = fopen(filename,'r');
heading = textscan(fid,'%s %s %s',1);
fgetl(fid); %advance the file pointer one line
data = textscan(fid,'%n %n %n');%read the rest of the data
fclose(fid);
In this case 'heading' will be a cell array containing cells with each column heading inside, so you will have to change them into cell array of strings or whatever it is that you want. 'data' will be a cell array containing a numeric array for each column that you read, so you will have to cat them together to make one matrix.

Related

Converting csv of strings into a matrix

I just started using Octave (No money for Matlab :/) and I'm also new to Stack Overflow, so please pardon any error I make with conventions.
Problem: I have a csv of strings like so:
Bob Marley,Kobe Bryant,Michael Jackson,Kevin Hart
I would like to make this into a 1 column matrix (I need it in a matrix so that I can combine it with data that are in other matrices).
My approach: I have tried doing textread, but this gives me a cell array. I tried converting the resulting cell array to a matrix by using cell2mat, but I suspect that I cannot do this because my strings are of varying lengths.
Let me know if any other information is necessary.
You can use char arrays using:
fid = fopen('strings.csv');
A = textscan(fid, '%s', 'delimiter', ',');
B = char(A{:})
[rows, cols] = size(B)
Output is the following:
B =
Bob Marley
Kobe Bryant
Michael Jackson
Kevin Hart
rows = 4
cols = 15
As you can see, the number of columns of B is the maximum length of all "strings" (Michael Jackson, 15). All other "strings" get whitespaces appended.
Considering you are in the directory where you have a file "strings.csv" with the content you mentioned in the question, your code whould look like this:
fid=fopen('strings.csv');
A=textscan(fid,'%s','delimiter',',');
A=A{1};
A=cellfun(#(x) string(x),A,'uni',0);
B=[A{:}];
If your data is that simple, you can do it in a one-liner. Use fileread to slurp all the data in, and then strsplit to separate the elements, and a ' transpose to convert it to a column vector.
x = strsplit(fileread('myfile.txt'), ',')'
If you end up with spaces around the commas in your data, upgrade to regexp.
x = regexp(fileread('myfile.txt'), ' *, *', 'split')

How to assign a matrix to a cell of a cell array

I'm working on matlab and try to assign a matrix to one cell of a cell array. However, there was always something wrong. Here is the code:
C = {};
myMatrix = xlsread('myexcelfile');
C{'ID', 'info'} = myMatrix;
Then matlab prompted that
"Expected one output from a curly brace or dot indexing expression, but there were 12 results."
But if I don't use 'ID' and 'Info' but use '1' and '2' instead, the matrix could be assigned successfully.
Could anyone help me? Thanks!
Assuming we have got three persons and each one has got a name and ID number and the data size that corresponds to each person is 2x3. I utilize a cell for storing data and fill it via random number.(In your case you should use xlsread('myexcelfile') to fill this cell). Each ID number is concatenated with a string because Matlab does not accept a string which is directly converted by number, for names in rows and columns of the table.
clc;clear all;close all;
% assuming we have got three persons in the dataset
cell_data=cell(3,3); % I use cell instead of matrix for storing data
ID_number=[38;48;58];% this vector contains the ID numbers of each person
for i=1:numel(ID_number);rng('shuffle');cell_data{i,i}=rand(2,3);end % using random number as dataset
ID=strcat('ID ',string(ID_number));%'38' is not a valid variable name so concat number with 'ID ' string
Customer = string({'Jones';'Brown';'Smith'});
Customer = cellstr(Customer);
T = table('RowNames',Customer);
for i=1:numel(ID_number)
T.(char(ID(i)))=cell_data(:,i);
end
%
After creating our table we can get input as follows:
input_cell = inputdlg({'Name','ID number'});% 2x1 cell
ID_input=strcat('ID ',input_cell{2,1});
T( {input_cell{1,1}} , {ID_input} )
And if the input formats are adapted to the table, we can get output like this:
table
ID48
____________
Brown [2×3 double]
You can add some conditions to the script for the cases that inputs are not adapted to the table format.

Printing progress in command window

I'd like to use fprintf to show code execution progress in the command window.
I've got a N x 1 array of structures, let's call it myStructure. Each element has the fields name and data. I'd like to print the name side by side with the number of data points, like such:
name1 number1
name2 number2
name3 number3
name4 number4
...
I can use repmat N times along with fprintf. The problem with that is that all the numbers have to come in between the names in a cell array C.
fprintf(repmat('%s\t%d',N,1),C{:})
I can use cellfun to get the names and number of datapoints.
names = {myStucture.name};
numpoints = cellfun(#numel,{myStructure.data});
However I'm not sure how to get this into a cell array with alternating elements for C to make the fprintf work.
Is there a way to do this? Is there a better way to get fprintf to behave as I desire?
You're very close. What I would do is change your cellfun call so that the output is a cell array instead of a numeric array. Use the 'UniformOutput' flag and set this to 0 or false.
When you're done, make a new cell array where both the name cell array and the size cell array are stacked on top of each other. You can then call fprintf once.
% Save the names in a cell array
A = {myStructure.name};
% Save the sizes in another cell array
B = cellfun(#numel, {myStructure.data}, 'UniformOutput', 0);
% Create a master cell array where the first row are the names
% and the second row are the sizes
out = [A; B];
% Print out the elements side-by-side
fprintf('%s\t%d\n', out{:});
The trick with the third line of code is that when you unroll the cell array using {:}, this creates a comma-separated list unrolled in column-major format, and so doing out{:} actually gives you:
A{1}, B{1}, A{2}, B{2}, ..., A{n}, B{n}
... which provides the interleaving you need. Therefore, providing this order into fprintf coincides with the format specifiers that are specified and thus gives you what you need. That's why it's important to stack the cell arrays so that each column gives the information you need.
Minor Note
Of course one should never forget that one of the easiest ways to tackle your problem is to just use a simple for loop. Even though for loops are considered bad practice, their performance has come a long way throughout MATLAB's evolution.
Simply put, just do this:
for ii = 1 : numel(myStructure)
fprintf('%s\t%d\n', myStructure(ii).name, numel(myStructure(ii).data));
end
The above code is arguably more readable in comparison to what we did above with cell arrays. You're accessing the structure directly rather than having to create intermediate variables for the purpose of calling fprintf once.
Example Run
Here's an example of this running. Using the data shown below:
clear myStructure;
myStructure(1).name = 'hello';
myStructure(1).data = rand(5,1);
myStructure(2).name = 'hi';
myStructure(2).data = zeros(3,3);
myStructure(3).name = 'huh';
myStructure(3).data = ones(6,4);
I get the following output after running the printing code:
hello 5
hi 9
huh 24
We can see that the sizes are correct as the first element in the structure is simply a random 5 element vector, the second element is a 3 x 3 = 9 zeroes matrix while the last element is a 6 x 4 = 24 ones matrix.

MATLAB Creating a .txt file containing numbers and strings from a cell

Dear stackoverflowers,
I'd like to create a .txt file using matlab.
The content should be separated with tabs.
It should have 3 columns, and the 3rd column should be filled with strings from a cell array.
Let's say
A=[2; 3; 3;];
B=2*A;
C=cell(3,1);
C{1,1}='string1'; C{2,1}='string2'; C{3,1}='string3';
In the end, it should look like this:
2 4 string1
3 6 string2
3 6 string3
I already found out, how to put the 2 matrices in a text file:
dlmwrite('filename.txt', [A B], 'delimiter', '\t')
But how to append the content of the cell?
It would be best, to have only the strings in the file, not the single quotes.
I neither found a solution to this elsewhere, nor did I ask this somewhere else.
I apprechiate all kinds of suggestions.
Try the following:
% Open a file for writing (if you want to append to file use 'a' instead of 'w')
fid = fopen(file,'w');
for i = 1:size(A,1)
fprintf(fid,'%d %d %s\n',A(i),B(i),C{i})
end
fclose(fid)
Hope this helps
the documentation on dlmwrite states:
Remarks
The resulting file is readable by spreadsheet programs.
The dlmwrite function does not accept cell arrays for the input matrix
M. To export a cell array that contains only numeric data, use
cell2mat to convert the cell array to a numeric matrix before calling csvwrite.
To export cell arrays with mixed alphabetic and numeric
data, where each cell contains a single element, you can create an
Excel spreadsheet (if your system has Excel installed) using xlswrite.
For all other cases, you must use low-level export functions to write
your data.
So either you write it as an Excel spreadsheet, or use have to write your own conversion function.
For example
A=[2; 3; 3;];
B=2*A;
C=cell(3,1);
C{1,1}='string1'; C{2,1}='string2'; C{3,1}='string3';
% First solution
f = fopen('filename.txt', 'w');
for n = 1:3
fprintf(f, '%d\t%d\t%s\n', A(n), B(n), C{n});
end
fclose(f);
% Another solution
% create the table as a single cell array with only strings
C2 = [arrayfun(#num2str, [A, B], 'UniformOutput', false) C]'; % <- note the transpose
f = fopen('filename.txt', 'w');
fprintf(f, '%s\t%s\t%s\n', C2{:}); % <- every three entries are written as a line
fclose(f);

regarding saving the numerical and string values altogether

I have a string matrix with N rows and 2 columns. Each cell stores a string. I have another N*1 vector, where each entry is a numerical value.
How can I save these two structures into a single text file row by row.
In other words, each row of the saved text file is composed of three elements, the first two elements come from a row of the string matrix and the third element comes from the corresponding row of that vector.
Thanks.
If I understand correctly, then fake data can be represented as this:
% Both have N=2 rows
strMat1 = {'a','b';'c','d';};
strMat2 = {1;2};
And if you want the output of this data to be a text file with:
ac1
bd2
Then you should do this:
txtOut = [];
if size(strMat1,1) == size(strMat2,1);
for row = 1:size(strMat1,1)
txtOut= [txtOut strMat1{:,row} num2str(strMat2{row}) '\n'];
end
else
disp('Size disagreement')
end
fid=fopen('textData.txt','wt');
fprintf(fid,txtOut)
It checks the vectors to make sure there are the same number of rows and then creates a txtOut string to be passed to a fprintf command.
Hope this helps! If you wanted the output to be spaced differently, just add spaces to the appending line in the form of ' ' .