MATLAB write string and then table to file - matlab

I need to write a string and a table to one text file. The string contains a description of the data in the table, but is not the headers for the table. I am using R2019a which I guess means the "Append" writetable option does not work? Please see my example data below:
% Load data
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
string = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
% How I tried to do this (which does not work!)
fid = fopen(filename, 'w', 'n');
fprintf(fid, '%s', cell2mat(string))
fclose(fid);
writetable(table, filename, 'FileType', 'text', 'WriteVariableNames', 0, 'Delimiter', 'tab', 'WriteMode', 'Append')
I get this error:
Error using writetable (line 155)
Wrong number of arguments.
Does anyone have a suggestion as to how to proceed?
Thanks!

A bit hacky, but here's an idea.
Convert your existing table to a cell array with table2cell.
Prepend a row of cells which consists of your string, followed by empty cells.
Convert the cell array back to a table with cell2table, and write the new table to the file.
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
s = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
new_table = cell2table([[s repmat({''},1,size(table,2)-1)] ; table2cell(table)]);
writetable(new_table,filename,'FileType','text','WriteVariableNames',0,'Delimiter','tab');
>> !head dummyoutput.sfc
This is a string about the cereal table
70 5 0.33 1 10 N 100% Bran 280
120 8 -1 5 2 Q 100% Natural Bran 135
70 7 0.33 1 9 K All-Bran 320
50 8 0.5 0 14 K All-Bran with Extra Fiber 330
110 14 0.75 2 1 R Almond Delight -1
110 10.5 0.75 2 1.5 G Apple Cinnamon Cheerios 70
110 11 1 0 1 K Apple Jacks 30
130 18 0.75 2 2 G Basic 4 100
90 15 0.67 1 4 R Bran Chex 125

Related

Import matlab with space and tab delimiter

I need to import a txt file into Matlab which has this format
text text text
1 0 1 2 3
4 5 6 7
2 10 11 15 18
15 1 18 3
The first column is separated with the second one by a tab delimiter, while the rest of the data are separated by a space.
I tried to import it using this:
g = importdata('file.txt',delimiterIn,headerlinesIn);
delimiterIn = ' ';
headerlinesIn = 1;
but then the extracted table is like this:
text text text
1 0 1 2 3
4 5 6 7 nan
2 10 11 15 18
15 1 18 3 nan
What I want is a table that maintains the format, with the first column of g.data on its own and then all the others.
I want an output matrix like
1 0 1 2 3
4 5 6 7
2 10 11 15 18
15 1 18 3
Then if I need to extract data represented by 2 in the first column, I can put it into another matrix with the values
10 11 15 18
15 1 18 3
each number inside a cell of a matrix
How can I do it?
A sollution might be:
fid = fopen('test.txt');
M = {[]};Midx=1;
l = fgetl(fid); %header
l = fgetl(fid);
while ~isnumeric(l)
idx = str2double(l(1));
if ~isnan(idx)
Midx=idx;
M{Midx}=[];
l = l(2:end);
end
val = cell2mat(textscan(l,'%f'))';
M{Midx}=[M{Midx};val];
l=fgetl(fid);
end
fclose(fid);
Maybe a bit too pragmatic, but this might help:
for i=1:size(A,1)
if isnan(A(i,end))==1
A(i,2:end) = A(i,1:4);
A(i,1) = NaN;
end
end
for i=1:size(A,1)
if A(i,1)==2
B = A(i:i+1,2:end);
end
end

How to load a text file in Matlab when the number of values in every line are different

I have a none rectangular text file like A which has 10 values in first line, 14 values in 2nd line, 16 values in 3rd line and so on. Here is an example of 4 lines of my text file:
line1:
1.68595314026 -1.48498177528 2.39820933342 27 20 15 2 4 62 -487.471069336 -517.781921387 5 96 -524.886108398 -485.697143555
Line2:
1.24980998039 -0.988095104694 1.89048337936 212 209 191 2 1 989 -641.149658203 -249.001220703 3 1036 -608.681762695 -300.815673828
Line3:
8.10434532166 -4.81520080566 4.90576314926 118 115 96 3 0 1703 749.967773438 -754.015136719 1 1359 1276.73632813 -941.855895996 2 1497 1338.98852539 -837.659179688
Line 4:
0.795098006725 -0.98456710577 1.89322447777 213 200 68 5 0 1438 -1386.39111328 -747.421386719 1 1565 -1153.50915527 -342.951965332 2 1481 -1341.57043457 -519.307800293 3 1920 -1058.8828125 -371.696960449 4 1303 -1466.5802002 -308.764587402
Now, I want to load this text file in to a matrix M in Matlab. I tired to use importdata function for loading it
M = importdata('A.txt');
but it loads the file in a rectangular matrix (all rows have same number of columns!!!) which is not right. The expected created matrix size should be like this:
size(M(1,:))= 1 10
size(M(2,:))= 1 14
size(M(3,:))= 1 16
How can I load this text file in a correct way into Matlab?
As #Jens suggested, you should use a cell array. Assuming your file contains only numeric values separated by whitespaces, for instance:
1 3 6
7 8 9 12 15
1 2
0 3 7
You can parse it into cell array like this:
% Read full file
str = fileread('A.txt');
% Convert text in a cell array of strings
c = textscan(str, '%s', 'Delimiter', '\n');
c = c{1};
% Convert 'string' elements to 'double'
n = cellfun(#str2num, c, 'UniformOutput', false)
You can then access individual lines like this:
>> n{1}
ans =
1 3 6
>> n{2}
ans =
7 8 9 12 15

Matlab: Find a string in a text file

I've searched around, bud didn't find a proper solution. So I ask it again.
There many lines in the .txt file. Looks Like this:
PRINT CONTENTS OF SUPERELEMENT yg_bde
PRINT OPTION = 3
HEADER =
8 55 2 12 6
13 0 13 11 0
1 1 0 0 1
0 0 1 78 14014
0 1584 166 103 yg_b
de 1561 0
922 931 1105 1121 1144
1158 1323 1503 0 989
1047 110005225 0 0 3
0 0
419 0 0 0 0
0 0 0 0
HEADER SUMMARY:
NUMBER OF ROWS = 55
NUMBER OF MATRICES = 2
NUMBER OF EDGE PLOT LINES = 12
NUMBER OF DEGREES OF FREEDOM PER NODE = 6
NUMBER OF DEGREE OF FREEDOM INDICES = 13
NUMBER OF NODES = 11
NUMBER OF LOAD VECTORS = 1
NUMBER OF TRANSFORMATIONS = 0
BASE FILE NAME= yg_bde
I need to locate the NUMBER OF ROWS = 55 and get the row number.
I think what need to do is
1. find and locate the Number of ROWS
2. Turn this line into number, so I can get the 55 number
I tried strfind(file ,string), but it can't return the line number, just the index when the file is in one line.
So, How can I Locate the NUMBER OF ROWS?
UPDATE:
whos data
Name Size Bytes Class Attributes
data 1x1 3094 struct
Approach #1
importdata based approach -
%// Import text data as a cell array with each cell holding each row of text data
data = importdata(inputfile,'\n') %// Edit inputfile to the path of your text file
%// Find the row(s) that holds the string 'NUMBER OF ROWS'
row_idx = find(~cellfun('isempty',strfind(data,'NUMBER OF ROWS')))
%// Find the number(s) in that/those row(s)
num = arrayfun(#(x) regexp(data{x}, '\d+', 'match'),row_idx)
Output I got -
row_idx =
19
num =
'55'
Now, num is a cell array. If you would like to have a numeric array, wrap it with str2double -
num_array = str2double(num)
Note: This also works if you have multiple lines with the string 'NUMBER OF ROWS'.
Approach #2
Alternative fgetl based approach that works by reading the text file line-by-line -
fid = fopen(inputfile); %// Edit inputfile to the path of your text file
tline = fgetl(fid);
num = [];
while ischar(tline)
if ~isempty(strfind(tline,'NUMBER OF ROWS'))
num = [num regexp(tline, '\d+', 'match')]; %#ok<AGROW>
end
tline = fgetl(fid);
end
fclose(fid);
num_array = str2double(num)

Writing on an existing mixed numeric and string text file with different field

I have a mixed numeric and string text file with different fields divided by [ ]. Some of its content is like:
[JUNCTIONS]
;ID Elev Demand Pattern
2 0 0 ;
9 0 0 ;
5 0 11 ;
6 0 20 ;
[RESERVOIRS]
;ID Head Pattern
1 5 ;
4 50 ;
[PIPES]
;ID Node1 Node2 Length Diameter Roughness MinorLoss Status
66 2 9 1000 250 100 0 Open ;
2 9 4 1000 150 100 0 Open ;
3 9 5 1000 150 100 0 Open ;
4 2 6 1000 150 100 0 Open ;
I want to overwrite numeric variables below the columns "Demand" and "Roughness" from MATLAB.
Would you please help me. I read about the performance of import and export commands of Matlab, but I couldn't find the solution.
Here is a small script that will read all your data into a cell array. Each cell is a column of data. As Divakar said, make your data is vertically aligned or textscan will stop when one of the lines is not the same as the last.
fid = fopen(file,'r');
while 1
line=fgetl(fid);
if ~strcmp(line,'')
if ~isempty(strfind(line,'['))
% //Let's check it
start = strfind(line,'[');
split = strfind(line,']');
category = line(start+1:split-1);
if strcmp(category,'PIPES')
break;
end
end
end
end
% //skip the header line
line=fgetl(fid);
% //So now we're on the right line, let's read in the table.
data = textscan(fid,'%d %d %d %d %d %d %d %s');
fclose(fid);

display a numeric mat as dataset (with Row/Col Names) in MATLAB

I'm not very familiar with datasets / displaying data in a readable format in Matlab. I have a numeric matrix with say 4 cols and I need to display it as:
mydata1 = [100 200 400 40] ;
mydata2 = [1 2 3 4 ] ;
display it as -->
CovA CovB CovC CovD
Sys1 100 200 400 40
Sys2 1 2 3 4
I am guessing datasets would help me implement this. Once converted, I'm hoping to publish this dataset with others. Thanks!
DATASET constructs data column-wise. Consequently, you can either accept that everything is transposed, i.e.
ds = dataset({mydata1','sys1'},{mydata2','sys2'},'obsNames',...
{'CovA','CovB','CovC','CovD'})
ds =
sys1 sys2
CovA 100 1
CovB 200 2
CovC 400 3
CovD 40 4
or you construct the dataset rather inconveniently by first catenating mydata:
mm = [mydata1;mydata2];
dataset(mm(:,1),mm(:,2),mm(:,3),mm(:,4),'varNames',...
{'CovA','CovB','CovC','CovD'},'obsNames',{'sys1','sys2'})
ans =
CovA CovB CovC CovD
sys1 100 200 400 40
sys2 1 2 3 4
This will display a matrix as a table in matlab
http://www.mathworks.com/matlabcentral/fileexchange/27384-disptable-display-matrix-with-column-or-row-labels