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)
Related
I have used xlsread in order to read a spreadsheet as a two dimensional matrix but I need to read a spreadsheet in the form of
2,2 2,0
0,2 1,1
As a 2,2,2 matrix
Is there a way to use Matlab to separate the values of the cells or do I have to use two separate matrices in the spreadsheet
If the data in the spreadsheet is one number per cell, just import the data into a 2D array. The command 'reshape' can change the dimensionality of the array, but it's sometimes a little tricky to get things to reorder the way you want them. This code will take a 2D vector M of size Rx(2C) and turn it into a 3D data block of size [R C 2] alternating pages across the rows of the original. It's hard to tell with your numbers that it's working so I used a different set that's easier to keep track of.
M = [1 2 3 4
5 6 7 8];
M = reshape(M,[size(M,1) 2 size(M,2)/2]);
M = permute(M,[1 3 2])
Which results in:
M(:,:,1) =
1 3
5 7
M(:,:,2) =
2 4
6 8
If the data in the spreadsheet has two values per cell separated by a comma (as suggested in the comments), it will import into MATLAB as a series of cell arrays. Consider a spreadsheet with 4 cells (2x2) with the following data:
[ 1,2 ][ 3,4 ]
[ 5,6 ][ 7,8 ]
In MATLAB we can load this using
[~,TXT]=xlsread('filename.xlsx');
And variable TXT would be:
TXT =
2×2 cell array
{'1,2'} {'3,4' }
{'5,6'} {'7,8'}
Operating on cells is a pain. I can't think of a way to do this without 'for' loops but once you're doing that, assigning to the third dimension is easy.
M = zeros([size(TXT,1) size(TXT,2) 2]);
for ii = 1:size(TXT,1)
for jj = 1:size(TXT,2)
temp = sscanf(char(TXT(ii,jj)),'%f,%f');
M(ii,jj,:) = reshape(temp,[1 1 2]);
end
end
For the values above
M(:,:,1) =
1 3
5 7
M(:,:,2) =
2 4
6 8
Below is the sample code that describe my issue.
ff= [{'1 2 3 4 5'};{'2 2 3 4 2'};{'3 2 3 4 3'};{'4 2 3 4 4'}];
YY=[];
for i=1:length(ff)
xx=str2num(ff{i,1});
YY=[YY;xx];
end
similar to the sample code my real length of ff length is very large and it is taking longer to finish the conversion. is there a way to make it faster?
Your solution is going to be particularly slow since you keep expanding the size of YY every time through the for loop.
To optimize this, you could first convert your cell array of strings into one long string using strjoin. Then you can apply str2num to this entire string at once and reshape the result.
YY = reshape(str2num(strjoin(ff)), [], numel(ff)).'
% 1 2 3 4 5
% 2 2 3 4 2
% 3 2 3 4 3
% 4 2 3 4 4
If your version of MATLAB doesn't have strjoin, you can always replace it with sprintf
YY = reshape(str2num(sprintf('%s ', ff{:})), [], numel(ff)).';
Another option would be to convert each entry of the cell array to numbers using cellfun and num2str and then concatenate the result along the first dimension.
values = cellfun(#num2str, ff, 'UniformOutput', false);
YY = cat(1, values{:});
The first option is about twice as fast since you call num2str only once and the memory needed to store the temporary string created by strjoin is going to be less than the space required to store the same data as a numeric datatype (double).
I have a text file which have 5 columns. Here is sample data:
book 1 3 5 7
paper 3 9 0 2
pen 3 1 2 0
pencil 9 0 3 9
The first column contains character and the other columns are just number. The file contains several rows. I am trying to read that .txt as follows;
fileID = fopen('filename.txt');
C = textscan(fileID,'%s %n %n %n %n');
fclose(fileID);
celldisp(C)
It read the column correctly. However, it reads only the first row, and not all. Why it is happening that way? How to do if I want to read all rows and all columns. Thanks
I assume you want to create a cell array in which every cell contains a single element from your text file.
The code you provided so far is correct:
fileID = fopen('filename.txt');
C = textscan(fileID,'%s %n %n %n %n');
fclose(fileID);
However now each cell in C contains an entire column from your txt file:
where C{1,1} contains the first column, that are four strings (book, paper, pen, pencil).
Now it is time un "unwrap" such cells using this piece of code:
for i=1:size(C,2)
if(iscell(C{:,i}))
A(:,i)=reshape(C{:,i},length(C{:,i}),1);
else
A(:,i)=num2cell(reshape(C{:,i},length(C{:,i}),1));
end
end
that basically says "if the cell contains a cell (see C{1,1}) just unwrap its content in length(C{:,i}) different cells. As instead if the cell contains an array, assign each element of this array to a different cell.".
Now the cell array A has the form
and I hope this is what you're looking for.
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);
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.