Writing a mixed matrix of integers and strings to .csv in Matlab - matlab

Perhaps this question has been answered before but I can't seem to find any good documentation on it. So my problem is the following:
Suppose I have two vectors of the same length in Matlab
x = [1;2;3];
and
y = ['A';'B';'C'];
Basically I would like to create the matrix {x,y} (ie 3 rows, 2 columns) and then write it to a .csv file. So in the end I'd like to see a .csv file like
1,A
2,B
3,C
This is just a mocked-up example but really I have 75 columns with each being either a column of strings or numerics. Any suggestions are greatly appreciated!

Actually here is the solution
http://www.mathworks.com/help/matlab/import_export/write-to-delimited-data-files.html#br2ypq2-1
This works much simpler.

If you sort your data into a suitable cell
A = cell(3,2);
A{1,1} = 1;
A{2,1} = 2;
A{3,1} = 3;
A{1,2} = 'A';
A{2,2} = 'B';
A{3,2} = 'C';
you may then call this function:
cell2csv(filename,A)
function cell2csv(filename,cellArray,delimiter)
% Writes cell array content into a *.csv file.
%
% CELL2CSV(filename,cellArray,delimiter)
%
% filename = Name of the file to save. [ i.e. 'text.csv' ]
% cellarray = Name of the Cell Array where the data is in
% delimiter = seperating sign, normally:',' (default)
%
% by Sylvain Fiedler, KA, 2004
% modified by Rob Kohr, Rutgers, 2005 - changed to english and fixed delimiter
if nargin<3
delimiter = ',';
end
datei = fopen(filename,'w');
for z=1:size(cellArray,1)
for s=1:size(cellArray,2)
var = eval(['cellArray{z,s}']);
if size(var,1) == 0
var = '';
end
if isnumeric(var) == 1
var = num2str(var);
end
fprintf(datei,var);
if s ~= size(cellArray,2)
fprintf(datei,[delimiter]);
end
end
fprintf(datei,'\n');
end
fclose(datei);

Related

string compare and remove elements

I have a csv file which consists of a N-by-M table.
in the first colum each row consists of 6 different numbers and I need to detect if any of the numbers is identical and then print a error message
This is how I thought it should be writte
valid=true(height(Information),1);
for i=1:height(Information),1;
if Information{i, 1} == Information{:, 1}
fprintf('Invalid number in line %d', i);
valid(i)=false;
end
end
use third output of unique and histcounts:
% generate two matrices, one with 2 identical elements
A1 = rand(3);
A1(end,1) = A1(1);
A2 = rand(3);
% check identical elements
[~,~,ic] = unique(A1(:,1),'stable');
identicalNumbers = any(histcounts(ic,max(ic)) > 1) % true
[~,~,ic] = unique(A2(:,1),'stable');
identicalNumbers = any(histcounts(ic,max(ic)) > 1) % false
Edit it can be done even simpler:
identicalNumbers = numel(ic) > max(ic)
First read the csv file in a matrix called A. then try the following code:
uniqueVals = unique( A(:,1) );% find unique values of col 1
[r c] = size(uniqueVals);% r determines the number of unique values in A(:,1)
[rr cc] = size(A);% rr is total number of values in A(:,1)
if (r~=rr)
disp('identical numbers detected');
end
I have modified my code. The below code detect the same numbers in the firs column and tells you the index:
A = randi (8,6)
uniqueVals = unique( A(:,1) );
[c r] = size(uniqueVals);
for i=1:c
[m n]= size(find(A(:,1) == uniqueVals(i)));
if m>1
disp('same values detected in rows: ')
find(A(:,1) == uniqueVals(i))
end
end
check the code and give me a feedback.
I have downloaded youe csv file in my local drive. run the code and select the csv file using the dialog box.
clear
clc
[file_name, mach_path] = uigetfile( ...
{'*.csv', 'All CSV (*.csv)'}, ...
'Select File');
% If "Cancel" is selected then return
if isequal([file_name,mach_path],[0,0])
return
% Otherwise construct the fullfilename and Check and load the file
else
fileName = fullfile(mach_path,file_name);
end
fid = fopen(fileName,'r'); %# Open the file
lineArray = cell(100,1); %# Preallocate a cell array (ideally slightly
%# larger than is needed)
lineIndex = 1; %# Index of cell to place the next line in
nextLine = fgetl(fid); %# Read the first line from the file
while ~isequal(nextLine,-1) %# Loop while not at the end of the file
lineArray{lineIndex} = nextLine; %# Add the line to the cell array
lineIndex = lineIndex+1; %# Increment the line index
nextLine = fgetl(fid); %# Read the next line from the file
end
fclose(fid); %# Close the file
lineArray = lineArray(1:lineIndex-1); %# Remove empty cells, if needed
for iLine = 1:lineIndex-1 %# Loop over lines
lineData = textscan(lineArray{iLine},'%s',... %# Read strings
'Delimiter',',');
lineData = lineData{1}; %# Remove cell encapsulation
if strcmp(lineArray{iLine}(end),',') %# Account for when the line
lineData{end+1} = ''; %# ends with a delimiter
end
lineArray(iLine,1:numel(lineData)) = lineData; %# Overwrite line data
end
A = lineArray;
uniqueVals = unique( A(:,1) );
[cc ~] = size(uniqueVals);
for i=1:cc
[mm ~]= size(find(ismember(A(:,1),uniqueVals(i))));
if mm>1
second = find(ismember(A(:,1),uniqueVals(i)));
disp('same value detected in rows: ')
disp(second(2));
A(second(2),:) = [];
disp(A);
end
end

cellArray to csv

I found a function (see below) that creates .csv out of a cell array. I modified it so as to work with a cellArray{z}{g} instead of a cellArray{z, s}. In the resulting .csv file, everything that should be separated into several columns is in one column. So I have only one column with several rows. I don't know how to separate these. In the cellArray{1}{1} for example contains first a String, and then values like 13.4156. How could I enable each cell in cellArray{z}{g} to end up in a separate cell in the. csv file?
function cell2csv(filename, cellArray, delimiter)
% Writes cell array content into a *.csv file.
%
% CELL2CSV(filename,cellArray,delimiter)
%
% filename = Name of the file to save. [ i.e. 'text.csv' ]
% cellarray = Name of the Cell Array where the data is in
% delimiter = seperating sign, normally:',' (default)
%
% by Sylvain Fiedler, KA, 2004
% modified by Rob Kohr, Rutgers, 2005 - changed to english and fixed delimiter
if nargin<3
delimiter = ',';
end
datei = fopen(filename,'w');
for z=1:size(cellArray,1)
for g=1:length(cellArray{z})
var = eval(['cellArray{z}{g}']);
if size(var,1) == 0
var = '';
end
if isnumeric(var) == 1
var = num2str(var);
end
fprintf(datei,var);
end
fprintf(datei,'\n');
end
fclose(datei);
Take a look at the code below:
A = cell(3,1);
for ind1 = 1:3
A{ind1} = {ind1,ind1,'cat'};
end
%% Approach 1 - xlswrite
B = vertcat(A{:});
xlswrite('somefile.xls',B);
%% Approach 2 - printf
% A is 3x1 cell of (1x3 cell) objects
B = cellfun(#(x)[num2str(x) ','], vertcat(A{:}),'UniformOutput',false);
% B is 3x3 cell of (1x1 cell) objects
C = num2cell(B,2);
% C is 1x3 cell of (3x1 cell) objects
fid = fopen('somefile.csv','w');
for ind1 = 1:size(C,1)
fprintf(fid, '%s\n',[C{ind1}{:}]);
end
fclose(fid);
This can be solved by changing fprintf(datei,var); --> fprintf(datei,[var, ',']);
and then when opening the csv just use , as delimiter

How can I write different length and different datatypes data to a text file from matlab

Right now I can only write a fixed length data to the text file ,but I need to change to a variable length data.
My code:
fileID = fopen(logfilePathLocal,'at+');
formatSpec = '%s,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n';
fprintf(fileID,formatSpec,data{1,:});
fclose(fileID);
You can use %f instead of %d, and specify width and precision, e.g. width 3 and precision 5 would be %3.5f.
For more information on specifier syntax, see the fprintf reference in the matlab documentation.
EDIT: If what you mean instead is that you don't know "how many %d my format-string will end up having", you can construct the format-string manually first (e.g. by concatenaton, or by using sprintf), and then use the resulting string in fprintf, e.g.
N = 5; % number of data, subject to change on each run.
% construct format-string
s = '%s';
for i = 1:N-1; s = [s, '%d, ']; end
s = [s, '%d\n']; % final data point
% use it with fprintf to print your data
fprintf (s, 'The data is: ', data{1,:});
Following the answer from here, you can use the combination of eval and an array of characters to produce the desired format specification alongside the data entry you're looking to print into a file.
clear
clc
fid = fopen('file.txt','at+');
% Generate some random data in a cell
data = {rand(5,1) rand(3,1)};
% Calculate required dimensions for fprintf
% and store the results in file.txt
n = size(data,2);
m = [];
for i=1:n
m = [m size(data{i},1) - 1];
end
% Finally, we will have n = 2, m = [4 2]
% Produce the final dynamic code snippet
fmt = [];
for i=1:n
for j=1:m(i)
fmt = [fmt '%d,'];
end
fmt = [fmt '%d\n'];
eval(['fprintf(fid,fmt,data{' num2str(i) '});']);
fmt = [];
end
An example output which is borrowed from file.txt is:
9.063082e-01,8.796537e-01,8.177606e-01,2.607280e-01,5.943563e-01
2.251259e-02,4.252593e-01,3.127189e-01

Importing data block with Matlab

I have a set of data in the following format, and I would like to import each block in order to analyze them with Matlab.
Emax=0.5/real
----------------------------------------------------------------------
4.9750557 14535
4.9825821 14522
4.990109 14511
4.9976354 14491
5.0051618 14481
5.0126886 14468
5.020215 14437
5.0277414 14418
5.0352678 14400
5.0427947 14372
5.0503211 14355
5.0578475 14339
5.0653744 14321
Emax=1/real
----------------------------------------------------------------------
24.965595 597544
24.973122 597543
24.980648 597543
24.988174 597542
24.995703 597542
25.003229 597542
I have modified this piece of code from MathWorks, but I think, I have problems dealing with the spaces between each column.
Each block of data consist of 3874 rows and is divided by a text (Emax=XX/real) and a line of ----, unfortunately is the only way the software export the data.
Here is one way to import the data:
% read file as a cell-array of lines
fid = fopen('file.dat', 'rt');
C = textscan(fid, '%s', 'Delimiter','');
C = C{1};
fclose(fid);
% remove separator lines
C(strncmp('---',C,3)) = [];
% location of section headers
headInd = [find(strncmp('Emax=', C, length('Emax='))) ; numel(C)+1];
% extract each section
num = numel(headInd)-1;
blocks = struct('header',cell(num,1), 'data',cell(num,1));
for i=1:num
% section header
blocks(i).header = C{headInd(i)};
% data
X = regexp(C(headInd(i)+1:headInd(i+1)-1), '\s+', 'split');
blocks(i).data = str2double(vertcat(X{:}));
end
The result is a structure array containing the data from each block:
>> blocks
blocks =
2x1 struct array with fields:
header
data
>> blocks(2)
ans =
header: 'Emax=1/real'
data: [6x2 double]
>> blocks(2).data(:,1)
ans =
24.9656
24.9731
24.9806
24.9882
24.9957
25.0032
This should work. I don't think textscan() will work with a file like this because of the breaks between blocks.
Essentially what this code does is loop through lines between blocks until it finds a line that matches the data format. The code is naive and assumes that the file will have exactly the number of blocks lines per block that you specify. If there were a fixed number of lines between blocks it would be a lot easier and you could remove the first inner loop and replace with just ~=fgets(fid) once for each line.
function block_data = readfile(in_file_name)
fid = fopen(in_file_name, 'r');
delimiter = ' ';
line_format = '%f %f';
n_cols = 2; % Number of numbers per line
block_length = 3874; % Number of lines per block
n_blocks = 2; % Total number of blocks in file
tline = fgets(fid);
line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
block_n = 0;
block_data = zeros(n_blocks,block_length,n_cols);
while ischar(tline) && block_n < n_blocks
block_n = block_n+1;
tline = fgets(fid);
if ischar(tline)
line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
end
while ischar(tline) && isempty(line_data)
tline = fgets(fid);
line_data = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
end
line_n = 1;
while line_n <= block_length
block_data(block_n,line_n,:) = cell2mat(textscan(tline,line_format,'delimiter',delimiter,'MultipleDelimsAsOne',1));
tline = fgets(fid);
line_n = line_n+1;
end
end
fclose(fid)

Writing a cell (matlab) to a CSV file

How can I save this cell
data = cell([3 2]);
data{1,1} = 'Bla';
data{2,1} = 'Bla1';
data{3,1} = 'Bla2';
data{1,2} = '2';
data{2,2} = '3';
data{3,2} = '1'
to a csv file?
I tried
dlmwrite('C:\Users\Ro\Desktop\Mestrado\Resultados\Tabelas\VaR_tab.csv',data,'delimiter',';')
but it give this error message:
Error using dlmwrite (line 118)
The input cell array cannot be converted to a matrix.
I just tried this, and it worked:
filename = 'test';
cell2csv(filename,data)
with cell2csv available as
function cell2csv(filename,cellArray,delimiter)
% Writes cell array content into a *.csv file.
%
% CELL2CSV(filename,cellArray,delimiter)
%
% filename = Name of the file to save. [ i.e. 'text.csv' ]
% cellarray = Name of the Cell Array where the data is in
% delimiter = seperating sign, normally:',' (default)
%
% by Sylvain Fiedler, KA, 2004
% modified by Rob Kohr, Rutgers, 2005 - changed to english and fixed delimiter
if nargin<3
delimiter = ',';
end
datei = fopen(filename,'w');
for z=1:size(cellArray,1)
for s=1:size(cellArray,2)
var = eval(['cellArray{z,s}']);
if size(var,1) == 0
var = '';
end
if isnumeric(var) == 1
var = num2str(var);
end
fprintf(datei,var);
if s ~= size(cellArray,2)
fprintf(datei,[delimiter]);
end
end
fprintf(datei,'\n');
end
fclose(datei);
I copied the code cause I am not aware if the function is any longer available on MathWorks File Exchange. But Google should help too.