I'd like to write several messages and tables on the same .txt file.
For example:
x=[23.9,10.9,8.9,14.2]
y=[9.83,8.04,7.47,8.32]
file=fopen('Results.txt','wt');
fprintf(file,'Results1\n');
fprintf(file,'%.2f %.2f\r\n',x,y);
fprintf(file,'Results2\n');
fclose(file);
I get this result as .txt:
Results1
23.90 10.90
8.90 14.20
9.83 8.04
7.47 8.32
Results2
But I should get this one:
Results1
23.90 9.83
10.90 8.04
8.90 7.47
14.20 8.32
Results2
Instead of fprintf(file,'%.2f %.2f\r\n',x,y);), I was trying to use:
ResultsTable2 = table(x,y);
writetable(file,ResultsTable2);
but didn't succeed. How to write the required .txt file?
Careful examination of your output shows that all the elements of x were printed before all the elements of y.
The documentation confirms that this is the expected behavior. Check out this example
A1 = [9.9, 9900];
A2 = [8.8, 7.7 ; ...
8800, 7700];
formatSpec = 'X is %4.2f meters or %8.3f mm\n';
fprintf(formatSpec,A1,A2)
X is 9.90 meters or 9900.000 mm
X is 8.80 meters or 8800.000 mm
X is 7.70 meters or 7700.000 mm
Even though the arguments to fprintf are in the order A1, A2. It first prints all the values from A1, and then it prints all the values from A2 going in single index order.
Therefore, if you want to alternate values from x and y during printing, you need to interleave them in a new variable. There are several possible ways to do so.
One example,
XY = reshape([x;y], 1, []);
Then everything should print as expected
fprintf(file, '%.2f %.2f\r\n', XY);
% or if you want to print to command window
% fprintf('%.2f %.2f\r\n', XY);
23.90 9.83
10.90 8.04
8.90 7.47
14.20 8.32
The correct answer for how to output data with fprintf is given by Cecilia: each argument will be iterated completely through in the order it appears in the argument list, so you have to combine the data into one matrix argument that will be iterated through column-wise to generate the desired output.
You also mentioned trying to use a table and the writetable function, so I though I'd add the correct way to do that in case you were curious:
ResultsTable2 = table(x(:), y(:)); % Pass data as column vectors
writetable(ResultsTable2, 'Results.txt', 'WriteVariableNames', false);
Related
I am trying to define the following function in MATLAB:
file = #(var1,var2,var3,var4) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4)'];
However, I want the function to expand as I add more parameters; if I wanted to add the variable vark, I want the function to be:
file = #(var1,var2,var3,var4,vark) ['var1=' num2str(var1) 'var2=' num2str(var2) 'var3=' num2str(var3) 'var4=' num2str(var4) 'vark=' num2str(vark)'];
Is there a systematic way to do this?
Use fprintf with varargin for this:
f = #(varargin) fprintf('var%i= %i\n', [(1:numel(varargin));[varargin{:}]])
f(5,6,7,88)
var1= 5
var2= 6
var3= 7
var4= 88
The format I've used is: 'var%i= %i\n'. This means it will first write var then %i says it should input an integer. Thereafter it should write = followed by a new number: %i and a newline \n.
It will choose the integer in odd positions for var%i and integers in the even positions for the actual number. Since the linear index in MATLAB goes column for column we place the vector [1 2 3 4 5 ...] on top, and the content of the variable in the second row.
By the way: If you actually want it on the format you specified in the question, skip the \n:
f = #(varargin) fprintf('var%i= %i', [(1:numel(varargin));[varargin{:}]])
f(6,12,3,15,5553)
var1= 6var2= 12var3= 3var4= 15var5= 5553
Also, you can change the second %i to floats (%f), doubles (%d) etc.
If you want to use actual variable names var1, var2, var3, ... in your input then I can only say one thing: Don't! It's a horrible idea. Use cells, structs, or anything else than numbered variable names.
Just to be crytsal clear: Don't use the output from this in MATLAB in combination with eval! eval is evil. The Mathworks actually warns you about this in the official documentation!
How about calling the function as many times as the number of parameters? I wrote this considering the specific form of the character string returned by your function where k is assumed to be the index of the 'kth' variable to be entered. Array var can be the list of your numeric parameters.
file=#(var,i)[strcat('var',num2str(i),'=') num2str(var) ];
var=[2,3,4,5];
str='';
for i=1:length(var);
str=strcat(str,file(var(i),i));
end
If you want a function to accept a flexible number of input arguments, you need varargin.
In case you want the final string to be composed of the names of your variables as in your workspace, I found no way, since you need varargin and then it looks impossible. But if you are fine with having var1, var2 in your string, you can define this function and then use it:
function str = strgen(varargin)
str = '';
for ii = 1:numel(varargin);
str = sprintf('%s var%d = %s', str, ii, num2str(varargin{ii}));
end
str = str(2:end); % to remove the initial blank space
It is also compatible with strings. Testing it:
% A = pi;
% B = 'Hello!';
strgen(A, B)
ans =
var1 = 3.1416 var2 = Hello!
I am going to start illustration using a code:
A = 'G1(General G1Airlines american G1Fungus )';
Using regexp (or any other function) in Matlab I want to distinctively locate: G1, G1A and G1F.
Currently if I try to do something as:
B = regexp( A, 'G1')
It is not able to distinguish G1 with the G1A and G1F i.e. I need to force the comparison to find me only case with G1 and ignore G1A and G1F.
However, when I am searching for G1A then it should still find me the location of G1A.
Can someone please help ?
Edit: Another case for A is:
A = 'R1George Service SmalR1Al C&I)';
And the expression this time I need to find is R1 and R1A instead.
Edit:
I have a giant array containing A's and another big vector containing G1, R1, etc I need to search for.
If you want to find 'G1' but not 'G1A' or 'G1F' you can use
>> B = regexp(A, 'G1[^AF]')
B =
1
This will find 'G1' and the ^ is used to specify that it should not match any characters contained with []. Then you could use
>> B = regexp(A, 'G1[AF]')
B =
12 32
to find both 'G1A' and 'G1F'.
I have many large dataset arrays in my workspace (loaded from a .mat file).
A minimal working example is like this
>> disp(old_ds)
Date firm1 firm2 firm3 firm4
734692 880,0 102,1 32,7 204,2
734695 880,0 102,0 30,9 196,4
734696 880,0 100,0 30,9 200,2
734697 880,0 101,4 30,9 200,2
734698 880,0 100,8 30,9 202,2
where the first row (with the strings) already are headers in the dataset, that is they are already displayed if I run old_ds.Properties.VarNames.
I'm wondering whether there is an easy and/or fast way to make the first column as ObsNames.
As a first approach, I've thought of "exporting" the data matrix (columns 2 to 5, in the example), the vector of dates and then creating a new dataset where the rows have names.
Namely:
>> mat = double(old_ds(:,2:5)); % taking the data, making it a matrix array
>> head = old_ds.Properties.VarNames % saving headers
>> head(1,1) = []; % getting rid of 'Date' from head
>> dates = dataset2cell(old_ds(:,1)); % taking dates as column cell array
>> dates(1) = []; % getting rid of 'Date' from dates
>> new_ds = mat2dataset(mat,'VarNames',head,'ObsNames',dates);
Apart from the fact that the last line returns the following error, ...
Error using setobsnames (line 25)
NEWNAMES must be a nonempty string or a cell array of nonempty strings.
Error in dataset (line 377)
a = setobsnames(a,obsnamesArg);
Error in mat2dataset (line 75)
d = dataset(vars{:},args{:});
...I would have found a solution, then created a function (such to generalize the process for all 22 dataset arrays that I have) and then run the function 22 times (once for each dataset array).
To put things into perspective, each dataset has 7660 rows and a number of columns that ranges from 2 to 1320.
I have no idea about how I could (and if I could) make the dataset directly "eat" the first column as ObsNames.
Can anyone give me a hint?
EDIT: attached a sample file.
Actually it should be quite easy (but the fact that I'm reading your question means that having the same problem, I first googled it before looking up the documentation... ;)
When loading the dataset, use the following command (adjusted to your case of course):
cell_dat{1} = dataset('File', 'YourDataFile.csv', 'Delimiter', ';',...
'ReadObsNames', true);
The 'ReadObsNames' default is false. It takes the header of the first column and saves it in the file or range as the name of the first dimension in A.Properties.DimNames.
(see the Documentation, Section: "Name/value pairs available when using text files or Excel spreadsheets as inputs")
I can't download your sample file, but if you haven't yet solved the problem otherwise, just try the suggested solution and tell if it works. Glad if I could help.
You are almost there, the error message you got is basically saying that Obsname have to be strings. In your case the 'dates' variable is cell array containing doubles. So you just need to convert them to string.
mat = double(piHU(:,2:end)); % taking the data, making it a matrix array
head = piHU.Properties.VarNames % saving headers
head(1) = []; % getting rid of 'Date' from head
dates = dataset2cell(piHU(:,1)); % taking dates as column cell array, here dates are of type double. try typing on the command window class(dates{2}), you can see the output is double.
dates(1) = []; % getting rid of 'Date' from dates
dates_str=cellfun(#(s) num2str(s),dates,'UniformOutput',false); % convert dates to string, now try typing class(dates_str{2}), the output should be char
new_ds = mat2dataset(mat,'VarNames',head,'ObsNames',dates_str); % construct new dataset.
I have to read the simple text file I write on the end of this post (it is just a sctructured grid). In fortran it is so easy to do this, you just have to do:
read(fileunit,*)
read(fileunit,*) mc,nc
do j = 1, nc
read (fileunit, *) dummy, dummy, (xcor(j,i), i=1,mc)
enddo
is there an equivalent function in matlab that reads element by element and keeps reading after the newline like in fortran? I could not find it, all the function as fscanf, textscan etc read line by line and then i have to parse each line. Here is the file. thanks for any help A.
Gridfile version 8.675.44
8 3
eta= 1 0.00000000000000000E+00 1.50000000000000000E+02
4.50000000000000000E+02 6.00000000000000000E+02
4.50000000000000000E+02 6.00000000000000000E+02
4.50000000000000000E+02 6.00000000000000000E+02
eta= 2 0.00000000000000000E+00 1.50000000000000000E+02
3.00000000000000000E+02 4.50000000000000000E+02
7.50000000000000000E+02 9.00000000000000000E+02
4.50000000000000000E+02 6.00000000000000000E+02
eta= 3 0.00000000000000000E+00 1.50000000000000000E+02
3.00000000000000000E+02 4.50000000000000000E+02
7.50000000000000000E+02 9.00000000000000000E+02
4.50000000000000000E+02 6.00000000000000000E+02
There are many ways to do this, but perhaps you will like the way fscanf works, as in this example. After the file is opened by something like fin = fopen('gridfile.txt') and the header swallowed, you can use fscanf(f, 'x= %d'), and then fscanf(f, '%f'), which will read the entire block. fscanf does not stop at the end of a line if not instructed to do so. Taken together, a solution could look like
fin = fopen('gridfile.txt');
fgetl(fin);
% read data counts
cnt = fscanf(fin, '%d %d', 2);
mc = cnt(1);
nc = cnt(2);
xcor = zeros(nc, mc);
% read blocks of data
for j = 1 : nc
fscanf(fin, '%s %s', 2);
xcor(j, :) = fscanf(fin, '%f', mc)';
end
fclose(fin);
fscanf keeps matching the format specifier as long as possible, and returns only when no further consecutive matches can be found. The above examples uses this in two places. First, to extract the dimensionality cnt, in your example (8, 3), and second, to read eight consecutive floating point values per record.
I have a code for "for loop"
for i=1:4
statement...
y=sim(net, I);
end
now i need to export the value of y to excel sheet. for that i used..
xlswrite('output_data.xls', y, 'output_data', 'A1')
but my problem is that the ID of excel i.e. "A1" should change according to each iteration... in my case for iteration 1-> A1, iteration-> A2 and so on..
anybody please help me out ..
thanks in advance. for any assistance.. or suggestion..
You can store sim outputs in a vector (y(ii)) and save in the sheet with a single write. This is also more efficient since you perform a single bulk-write instead of many small writes.
Specify the first cell and y will be written starting from there.
last = someNumber;
for i=1:last statement... y(i)=sim(net, I); end
xlswrite('output_data.xls', y', 'output_data', 'A1');
If you prefer specify the range write ['A1:A',num2str(last)] instead of A1.
If you really want to write within the loop try:
for ii=1:last
...
y=sim(net, I);
xlswrite('output_data.xls', y, 'output_data', sprintf('A%d',ii));
end
You can also do for yourself what xlswrite does internally, which is interact using COM. I prefer to do this when I have a frequently used excel template or data file, because it allows for more control (albeit with more lines of code).
Excel = actxserver('Excel.Application');
Workbook = Excel.Workbooks.Open('myExcelFile.xlsx');
MySheet = Excel.ActiveWorkBook.Sheets.Item(1);
set( get(MySheet,'Range','A1:A10'), 'Value', yourValues);
...
invoke(Workbook, 'Save');
invoke(Excel, 'Quit');
delete(Excel);
This would allow you to save new data to new ranges without re-opening excel each time.
Even better would be to define an oncleanup function (as does xlswrite) to prevent lost file locks (especially when you're doing things like exiting out of debug mode):
...
myWorkbook = Excel.Workbooks.Open(filename,0,true);
cleanUp = onCleanup(#()xlsCleanup(Excel, filename));
function xlsCleanup(Excel,filepath)
try
Excel.DisplayAlerts = 0; %// Turn off dialog boxes
[~,n,e] = fileparts(filepath); %// Excel API expects just the filename
fileName = [n,e];
Excel.Workbooks.Item(fileName).Close(false);
end
Excel.Quit;
end
You can put xlswrite after for loop.You just want to do is save you result in a matrix.This function can write a matrix.
also,you can use [] to combine string to change the range.
>> for i=1:4
Range=['A' num2str(i)]
end
Range =
A1
Range =
A2
Range =
A3
Range =
A4
But,this is a bad way.You should open and write Excel file every time.