Writing to a text file in Matlab - matlab

I've come across numerous ways to write matlab data to a .txt file but I am unsure which way would be best suited for my needs - I have two sets of data labelled 'x' and 'y' within which data simply runs down 1 column (A1....An) and I need a tab delimited .txt file made with the format:
Name X X Y
Test 2 2 5.5
Test 3 3 6.5
Test 4 4 7.5
etc...
Whereby I can have 2 identical columns of the X data, followed by the Y data. I also need to be able to input something for the 'Name' column which will copy itself down until the data in X/Y stops. I don't need any column headers in it i.e. 'X' 'Y' or 'Name' just the data itself.
What would be the best way to go about this?

Run this code example and you can check that it does what you want:
% Example data:
x = [1:5];
y = rand(1,5);
fileID = fopen('yourfile.txt','w');
for i = 1:length(x)
fprintf(fileID,'%s\t%d\t%d\t%f\n', 'Test', x(i),x(i),y(i));
end
fclose(fileID);
Opening the text file you will see something like:
Test 1 1 0.655741
Test 2 2 0.035712
Test 3 3 0.849129
Test 4 4 0.933993
Test 5 5 0.678735
If you want the value for string 'Test' to change in each row, simply pass in an array with those string values, similar to how the x and y variables are passed to the fprintf() statement.

One way is to first put everything into a single cell:
Name = repmat({'Test'}, [1 DataSize]); % A Cell containing n 'Test' string
C = [Name num2cell(X') num2cell(X') num2cell(Y')]; % Concatenating cells
Then use fprintf to write the cell into a file:
fid = fopen('data.txt', 'wt');
fprintf(fid, '%s\t%d\t%d\t%d\n', C{:});
fclose(fid);
Hope it helps.

Related

How can I convert this table to a cell array as shown in the screenshot?

I am trying to convert a table imported from a CSV file (see below) and convert it to two cell arrays. As shown in the screenshots, Cell 1 contains "measure" of he table, measures of the same ID go in the same cell. Similarly Cell 2 contains "t" in the same way.
Matlab is not my language but I have a function to test out written in Matlab only, so I am really unsure how I could achieve this task.
Let the data be defined as
data = array2table([1 100 1; 1 200 2; 1 300 3; 2 500 3; 2 600 4; 2 700 5; 2 800 6], ...
'VariableNames', {'id' 'measure' 't'}); % example data
You can use findgroups and splitapply as follows:
g = findgroups(data.id); % grouping variable
result_measure = splitapply(#(x){x.'}, data.measure, g).'; % split measure as per g
result_t = splitapply(#(x){x.'}, data.t, g).'; % split t as per g
Alternatively, findgroups for a single grouping variable can be replaced by unique (third output), and splitapply for a single data variable can be replaced by accumarray:
[~, ~, g] = unique(data.id); % grouping variable
result_measure = accumarray(g, data.measure, [], #(x){x.'}).'; % split measure as per g
result_t = accumarray(g, data.t, [], #(x){x.'}).'; % split t as per g
In case someone is interested in my non-Matlab solution to the problem:
array_id=table2array(data(:,'id'));
array_t=table2array(data(:,'t'));
array_measure=table2array(data(:,'measure'));
uni_id=unique(array_id);
t_cell=cell(1,length(uni_id));
measure_cell=cell(1,length(uni_id));
for i=1:length(uni_id)
temp_t=table2array(data(data.id==uni_id(i),'t'));
temp_measure=table2array(data(data.id==uni_id(i),'measure'));
t_cell{i}=temp_t';
measure_cell{i}=temp_measure';
end
Apparently this is nothing comparable to what Luis has, but it gets the job done.

Importing Data from a .txt file into Matlab

First of all thank you for reading my question.
I am trying to import data from a file with following format into Matlab:
#Text
#Text: Number
...
#Text: Number
Set1:
1 2
3 4
Set2:
5 6
7 8
...
I would like to get those numbers into two matrices of the form:
(1 5
3 7)
and
(2 6
4 8)
I started by only building the first of those two matrices.
Winkel = 15;
xp = 30;
M = readtable('Ebene_1.txt')
M([1:4],:) = [];
M(:,3) = [];
for i=0:Winkel-1
A = table2array(M((2+i*31:31+i*31),1))
end
But this solution only gave me cell arrays which I could not transform into normal vectors.
I also tried to use the importdata command, but could not find a way to get this to work either. I know there are many other questions similar to mine, but I could not find one where all the data were in a single column. Also, there are many Matlab-commands for importing data into Matlab and I am not sure which would be the best.
First time asking such a question online so feel free to ask me for more details.
You can import the data you provided in your sample using readtable, however because of the format of your file you will need to tweak the function a bit.
You can use detectImportOptions to tell the function how to import the data.
%Detect import options for your text file.
opts = detectImportOptions('Ebene_1.txt')
%Specify variable names for your table.
opts.VariableNames = {'Text','Number'};
%Ignore last column of your text file as it does not contain data you are interested in.
opts.ExtraColumnsRule = 'ignore';
%You can confirm that the function has successfully identified that the data is numeric by inspecting the VariableTypes property.
%opts.VariableTypes
%Read your text file with detectImportOptions.
M = readtable('Ebene_1.txt',opts)
Now that you have table M, simply apply basic Matlab operations to obtain the matrices as you specified.
%Find numerical values in Text and Number variables. Ignore NaN values.
A = M.Text(~isnan(M.Text));
B = M.Number(~isnan(M.Number));
%Build matrices.
A = [A(1:2:end)';A(2:2:end)']
B = [B(1:2:end)';B(2:2:end)']
Output:
A =
1 5
3 7
B =
2 6
4 8

Read a complex, and long text file in Matlab

I have a very long text file which contains the data from 4 different stations with different time steps:
1:00
station 1
a number 1 (e.g.0.6E-06)
matrix1 (41x36)
station 2
number 2 (e.g.0.1E-06)
matrix2 (41x36)
station 3
number 3 (e.g.0.2E-06)
matrix3 (41x36)
station 4
number 4 (e.g.0.4E-06)
matrix4 (41x36)
2:00
station 1
a number (e.g.0.24E-06)
matrix5 (41x36)
station 2
a number (e.g.0.3E-06)
matrix6 (41x36)
station 3
number (e.g.0.12E-06)
matrix7 (41x36)
station 4
number (e.g.0.14E-06)
matrix8 (41x36)
.....
and so on
I need to read this data by each station and each step, and noted that each matrix should be scaled by multiplying with a number above it. An example is here: https://files.fm/u/sn447ttc#/view/example.txt
Could you please help?
Thank you a lot.
My idea here would be to read the textfile using fopen and textscan. Afterwards you can search for appearances of the Keyword FACTOR to subdivide the output. Here's the code:
fid=fopen('example.txt'); % open the document
dataRaw=textscan(fid,'%s','Delimiter',''); % read the file with no delimiter to achieve a cell array with 1 cell per line of the text file
fclose(fid); % close the document
rows=cellfun(#(x) strfind(x,'FACTOR'),dataRaw,'uni',0); % search for appearances of 'FACTOR'
hasFactor=find(~cellfun(#isempty,rows{1})); % get rownumbers of the lines that contain the word FACTOR
dataRaw=dataRaw{1}; % convert array for easier indexing
for ii=1:(numel(hasFactor)-1) % loop over appearances of the word FACTOR
array=cellfun(#str2num,dataRaw(hasFactor(ii)+2:hasFactor(ii+1)-1),'uni',0); % extract numerical data
output{ii}=str2num(dataRaw{hasFactor(ii)+1})*cat(1,array{:}); % create output scaled by the factor
end
array=cellfun(#str2num,dataRaw(hasFactor(end)+2:end),'uni',0);
output{end+1}=str2num(dataRaw{hasFactor(end)+1})*cat(1,array{:}); % These last 2 lines add the last array to the ouput
outputMat=cat(3,output{:}); % convert to a 3-dimensional matrix
outputStations=[{output(1:4:end)} {output(2:4:end)} {output(3:4:end)} {output(4:4:end)}]; % Sort the output to have 1 cell for each station
outputColumnSums=cellfun(#(x) cellfun(#sum,x,'uni',0),outputStations,'uni',0); % To sum up all the columns of each matrix
outputRowSums=cellfun(#(x) cellfun(#(y) sum(y,2),x,'uni',0),outputStations,'uni',0);
This approach is pretty slow and probably can be vectorized, but if you don't need it to be fast it should do the job. I created a cell-output with 1 cell per array and a 3 dimensional array as optional output. Hope that's fine with you
I have looked into your situation and it seems that the problem not trivial as anticipated. Keep in mind that if I have made mistakes on the assumption of the location of the data, you can let me know so I can edit it, or you can just change the numbers to that which suits your case. In this case, I initially loaded the delimited file into an Excel spreadsheet, just to visualize it.
After reading up on dlmread, I found that one can specify the exact rows and columns to pull from example.txt, as shown here:
data = dlmread('example.txt', ' ', [4 1 45 37]); % [r1 c1 r2 c2]
data2 = dlmread('example.txt', ' ', [47 1 88 37]);
The result of which is two matrices that are 41-by-37, containing only numbers. I started data at row 4 to bypass the header information/strings. Noticing the pattern, I set it up as a loop:
No_of_matrices_expected = 4;
dataCell = cell(No_of_matrices_expected, 1);
iterations = length(dataCell)
% Initial Conditions
rowBeginning = 4;
col1 = 1; % Constant
rowEnd = rowBeginning + 40; % == 44, right before next header information
col2 = 36; % Constant
for n = 1 : iterations
dataCell{n} = dlmread('example.txt', ' ', [rowBeginning, col1, rowEnd, col2]);
rowBeginning = rowBeginning + 41 + 2; % skip previous matrix and skip header info
rowEnd = rowBeginning + 40;
end
However, I stumbled across what you stated earlier which was that there are four different stations, each with their own time stamps. So running this loop more than 4 times led to unexpected results and MATLAB crashed. The reason is that the new timestamp creates an extra row for the date. Now, you could change the loop above to compensate for this extra row, or you can make multiple for loops for each station. This will be your decision to make.
Now if you wanted to save the header information, I would recommend taking a look into textscan. You can simply use this function to pull the first column of all the data into a cell array of strings. Then you can pull out the header information that you want. Keep in mind, use fopen if you want to use textscan.
I'll let you use what I have found thus far, but let me know if you need more help.
Numbers

Matlab write cell array of numbers into file

I have a cell array like this:
cellarr{1}=[1 2 3];
cellarr{2}=[1 2 3 4 5 6];
...
Each cell is a vector of numbers with different length. I want to write this cell array into a text file so that i can read it later. The text file should look like this:
1 2 3
1 2 3 4 5 6
If I use dlmwrite('file.txt',cellarr,'\t') it puts all cells into one line. How do I put a new line character after writing a cell to the text file?
P/S: I could use fprintf with two for loops to get what I want. But is there a faster way to do that?
I was wondering why do you need two for loops?
fid = fopen('file.txt', 'wt');
for i = 1 : length(cellarr)
fprintf(fid, '%d\t', cellarr{i});
fprintf(fid,'\n');
end
fclose(fid)

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);