MATLAB - Error while writing output in a CSV file using fprintf - matlab

I am consistently getting an error while writing output in a CSV file using fprintf. I actually want to write my results in a CSV file. I have tried different lengths of the matrix, and I get the same error even with two columns. What's the mistake here and how can I resolve this error?
Sample code:
colname = {'col1' 'col2' 'col3'};
fid = fopen('test.csv','w');
fprintf(fid, '%s, %s, %s\n', colname{1:});
for p=1:5
% <Some code>
fname = %reading image name from a directory
% <Some code>
val1 = %calculating value1
val2 = %calculating value2
datacol = {fname val1 val2};
fprintf(fid, '%s, %f, %f\n', datacol{p+1:});
end
fclose(fid);
Error:
??? Index exceeds matrix dimensions. at fprintf(fid, '%s, %f, %f\n', datacol{p+1:});
P.S.: Writing "datacol = {fname val1 val2};" as "datacol = {fname,val1,val2};" brought the same error message.

You are indexing the cell contents of datacol.
If I am not mistaken datacol looks sth like this:
{'some_string_for_the_name', 1, 2}
Where 1 and 2 are val1 and val2.
During your loop you access datacol{p+1} which obviously is datcol{4} for p = 3.
Since your cell only has three elements, indexing a fourth will result in an error. What you probably would like to do is print the lines of val1 and val2, no?
Changing your fprintf to
fprintf(fid, '%s, %f, %f\n', datacol{1}, datacol{2}, datacol{3});
should solve your problem.

Related

Issues printing a character string in Matlab

I'm new to MATLAB and I'm having problems printing a character array to a file. I only get the first character printed out. I read lines from a file and build an matrix of matrices. One matrix is an array of character vectors. Here's how I read the data
tline = fgetl(iin);
t_current = tline(9:34);
...
data.t = [data.t; t_current];
Then later I do this:
npts = length(data.t);
fid1 = fopen(fname, 'w');
fprintf(fid1, 'Day Rank\n');
fprintf(fid1, '------- -------\n');
for k = 1:npts
time_str = data.t(k);
fprintf(fid1, '%s %f3\n',time_str, data.rank(k));
end
fclose(fid1);
data.t is <10082,26 char> and looks something like this:
val =
2015-07-16T03:28:36.410305
2015-07-16T03:29:00.000000
...
All I get with the fprintf is a '2'. I tried to use convertCharsToStrings but that failed with an error message: Undefined function 'convertCharsToStrings' for input arguments of type
'char'.
This must be something simple I'm missing.
Thanks,
-Mike
Since "data.t is <10082,26 char>", try this:
...
for k = 1:npts
time_str = data.t(k, :);
...
If you do not use the , :, Matlab will use linear indexing for the matrix as opposed to subscripts.
It turns out I needed to use a different format for getting the time string:
time_str=data.t(k,1:end)

Matlab reading txt formatted file

If there is a .txt file in the format
Name, Home, 1, 2, 3, 3, 3, 3
It means the first two columns are string, and the rest are integers
How do I read first two column as vectors of strings, and another matrix as numeric values.
One way of doing this so you know exactly what's happening line by line is in the following piece of code:
fid = fopen('textfile.txt');
clear data
tline = fgetl(fid);
n = 1;
while ischar(tline)
data(n,:) = strsplit(tline(1:end),', ');
n=n+1;
tline = fgetl(fid);
end
fclose(fid);
dataStrings = data(:,1:2);
dataValues = str2double(data(:,3:end));
where data contains everything in string type, dataStrings contains only first 2 columns as strings, and dataValues contains the rest of the columns as type double.
This way you get simple matrices, meaning you don't have to worry yourself with structures or cell arrays.
Use textscan:
fileID = fopen('sometextfile.txt');
C = textscan(fileID,'%s %s %f %f %f %f %f %f','Delimiter',','); % assuming you want double data types, change as required
fclose(fileID);
celldisp(C) % C is a cell array

read a txt file to matrix and cellarray Matlab

I have a txt file with those entries and I would like to know how to get the numerical values from the second column until the last column in a matrix and the first column in a cell array.
I've tried with import data and fscanf and I dont understand what's going on.
CP6 7,2 -2,7 6,6
P5 -5,8 -5,9 5,8
P6 5,8 -5,9 5,8
AF7 -5,0 7,2 3,6
AF8 5,0 7,2 3,6
FT7 -7,6 2,8 3,6
This should give you what you want based on the text sample you supplied.
fileID = fopen('x.txt'); %open file x.txt
m=textscan(fileID,'%s %d ,%d %d ,%d %d ,%d');
fclose(fileID); %close file
col1 = m{1,1}; %get first column into cell array col1
colRest = cell2mat(m(1,2:6)); %convert rest of columns into matrix colRest
Lookup textscan for more info on reading specially formatted data
This function should do the trick. It reads your file and scans it according to your pattern. Then, put the first column in a cell array and the others in a matrix.
function [ C1,A ] = scan_your_txt_file( filename )
fid = fopen(filename,'rt');
C = textscan(fid, '%s %d,%d %d,%d %d,%d');
fclose(fid);
C1 = C{1};
A = cell2mat(C(2:size(C,2)));
end
Have you tried xlsread? It makes a numeric array and two non-numeric arrays.
[N,T,R]=xlsread('yourfilename.txt')
but your data is not comma delimited. It also looks like you are using a comma to represent a decimal point. Does this array have 7 columns or 4? Because I'm in the US, I'm going to assume you have paired coordinates and the comma is one kind of delimiter while the space is a second one.
So here is something klugy, but it works. It is a gross ugly hack, but it works.
%housekeeping
clc
%get name of raw file
d=dir('*22202740*.txt')
%translate from comma-as-decimal to period-as-decimal
fid = fopen(d(1).name,'r') %source
fid2= fopen('myout.txt','w+') %sink
while 1
tline = fgetl(fid); %read
if ~ischar(tline), break, end %end loop
fprintf(fid2,'%s\r\n',strrep(tline,',','.')) %write updated line to output
end
fclose(fid)
fclose(fid2)
%open, gulp, parse/store, close
fid3 = fopen('myout.txt','r');
C=textscan(fid3,'%s %f %f %f ');
fclose(fid3);
%measure waist size and height
[n,m]=size(C);
n=length(C{1});
%put in slightly more friendly form
temp=zeros(n,m);
for i=2:m
t0=C{i};
temp(:,i)=t0;
end
%write to excel
xlswrite('myout_22202740.xlsx',temp(:,2:end),['b1:' char(96+m) num2str(n)]);
xlswrite('myout_22202740.xlsx',C{1},['a1:a' num2str(n)])
%read from excel
[N,T,R]=xlsread('myout_22202740.xlsx')
If you want those commas to be decimal points, then that is a different question.

Reading CSV with mixed type data

I need to read the following csv file in MATLAB:
2009-04-29 01:01:42.000;16271.1;16271.1
2009-04-29 02:01:42.000;2.5;16273.6
2009-04-29 03:01:42.000;2.599609;16276.2
2009-04-29 04:01:42.000;2.5;16278.7
...
I'd like to have three columns:
timestamp;value1;value2
I tried the approaches described here:
Reading date and time from CSV file in MATLAB
modified as:
filename = 'prova.csv';
fid = fopen(filename, 'rt');
a = textscan(fid, '%s %f %f', ...
'Delimiter',';', 'CollectOutput',1);
fclose(fid);
But it returs a 1x2 cell, whose first element is a{1}='ÿþ2', the other are empty.
I had also tried to adapt to my case the answers to these questions:
importing data with time in MATLAB
Read data files with specific format in matlab and convert date to matal serial time
but I didn't succeed.
How can I import that csv file?
EDIT After the answer of #macduff i try to copy-paste in a new file the data reported above and use:
a = textscan(fid, '%s %f %f','Delimiter',';');
and it works.
Unfortunately that didn't solve the problem because I have to process csv files generated automatically, which seems to be the cause of the strange MATLAB behavior.
What about trying:
a = textscan(fid, '%s %f %f','Delimiter',';');
For me I get:
a =
{4x1 cell} [4x1 double] [4x1 double]
So each element of a corresponds to a column in your csv file. Is this what you need?
Thanks!
Seems you're going about it the right way. The example you provide poses no problems here, I get the output you desire. What's in the 1x2 cell?
If I were you I'd try again with a smaller subset of the file, say 10 lines, and see if the output changes. If yes, then try 100 lines, etc., until you find where the 4x1 cell + 4x2 array breaks down into the 1x2 cell. It might be that there's an empty line or a single empty field or whatever, which forces textscan to collect data in an additional level of cells.
Note that 'CollectOutput',1 will collect the last two columns into a single array, so you'll end up with 1 cell array of 4x1 containing strings, and 1 array of 4x2 containing doubles. Is that indeed what you want? Otherwise, see #macduff's post.
I've had to parse large files like this, and I found I didn't like textscan for this job. I just use a basic while loop to parse the file, and I use datevec to extract the timestamp components into a 6-element time vector.
%% Optional: initialize for speed if you have large files
n = 1000 %% <# of rows in file - if known>
timestamp = zeros(n,6);
value1 = zeros(n,1);
value2 = zeros(n,1);
fid = fopen(fname, 'rt');
if fid < 0
error('Error opening file %s\n', fname); % exit point
end
cntr = 0
while true
tline = fgetl(fid); %% get one line
if ~ischar(tline), break; end; % break out of loop at end of file
cntr = cntr + 1;
splitLine = strsplit(tline, ';'); %% split the line on ; delimiters
timestamp(cntr,:) = datevec(splitLine{1}, 'yyyy-mm-dd HH:MM:SS.FFF'); %% using datevec to parse time gives you a standard timestamp vector
value1(cntr) = splitLine{2};
value2(cntr) = splitLine{3};
end
%% Concatenate at the end if you like
result = [timestamp value1 value2];

Outputing cell array to CSV file ( MATLAB )

I've created a m x n cell array using cell(m,n), and filled each of the cells with arbitrary strings.
How do I output the cell array as a CSV file, where each cell in the array is a cell in the CSV 'spreadsheet'.
I've tried using cell2CSV, but I get errors ...
Error in ==> cell2csv at 71
fprintf(datei, '%s', var);
Caused by:
Error using ==> dlmwrite at 114
The input cell array cannot be converted to a matrix.
Any guidance will be well received :)
Here is a somewhat vectorized solution:
%# lets create a cellarray filled with random strings
C = cell(10,5);
chars = char(97:122);
for i=1:numel(C)
C{i} = chars(ceil(numel(chars).*rand(1,randi(10))));
end
%# build cellarray of lines, values are comma-separated
[m n] = size(C);
CC = cell(m,n+n-1);
CC(:,1:2:end) = C;
CC(:,2:2:end,:) = {','};
CC = arrayfun(#(i) [CC{i,:}], 1:m, 'UniformOutput',false)'; %'
%# write lines to file
fid = fopen('output.csv','wt');
fprintf(fid, '%s\n',CC{:});
fclose(fid);
The strings:
C =
'rdkhshx' 'egxpnpvnfl' 'qnwcxcndo' 'gubkafae' 'yvsejeaisq'
'kmsvpoils' 'zqssj' 't' 'ge' 'lhntto'
'sarlldvig' 'oeoslv' 'xznhcnptc' 'px' 'qdnjcdfr'
'jook' 'jlkutlsy' 'neyplyr' 'fmjngbleay' 'sganh'
'nrys' 'sckplbfv' 'vnorj' 'ztars' 'xkarvzblpr'
'vdbce' 'w' 'pwk' 'ofufjxw' 'qsjpdbzh'
'haoc' 'r' 'lh' 'ipxxp' 'zefiyk'
'qw' 'fodrpb' 'vkkjd' 'wlxa' 'dkj'
'ozonilmbxb' 'd' 'clg' 'seieik' 'lc'
'vkpvx' 'l' 'ldm' 'bohgge' 'aouglob'
The resulting CSV file:
rdkhshx,egxpnpvnfl,qnwcxcndo,gubkafae,yvsejeaisq
kmsvpoils,zqssj,t,ge,lhntto
sarlldvig,oeoslv,xznhcnptc,px,qdnjcdfr
jook,jlkutlsy,neyplyr,fmjngbleay,sganh
nrys,sckplbfv,vnorj,ztars,xkarvzblpr
vdbce,w,pwk,ofufjxw,qsjpdbzh
haoc,r,lh,ipxxp,zefiyk
qw,fodrpb,vkkjd,wlxa,dkj
ozonilmbxb,d,clg,seieik,lc
vkpvx,l,ldm,bohgge,aouglob
Last commment was written in "pure" C. So It doesnt work in Matlab.
Here it is the right solution.
function [ ] = writecellmatrixtocsvfile( filename, matrix )
%WRITECELLMATRIXTOCSVFILE Summary of this function goes here
% Detailed explanation goes here
fid = fopen(filename,'w');
for i = 1:size(matrix,1)
for j = 1:size(matrix,2)
fprintf(fid,'%s',matrix{i,j});
if j~=size(matrix,2)
fprintf(fid,'%s',',');
else
fprintf(fid,'\n');
end
end
end
fclose(fid);
end
easy enough to write your own csv writer.
-- edited to reflect comments --
fid = fopen('myfilename.csv','w');
for i = 1:size(A,1)
for j = 1:size(A,2)
fprintf(fid,'%s',A{i,j});
if(j!=size(A,2)
fprintf(fid,',',A{i,j})
else
fprintf(fid,'\n')
end
end
end
fclose(fid);