how to insert a custom string between two double array dimensions - arrays

I have an array called temp containing double-precision values with dimensions 240×20×10428 . I would like to write it to a text file. I tried the following:
dlmwrite(['e:\temp\', str, '.txt'], temp, 'precision', 10);
now the problem is how to add \r\n\r\n string(two enter pressed key) after each first dimension (we have 240th of this dimension) in the text file? what should I have done? I want to have this format after all:
0.324235,...(20*10428 numbers),0.4363423,\r\n\r\n,
0.5467354,...(20*10428 numbers),0.346564,...
NOTE: this array come from .nc files and I want to convert them into .txt file using this way

The handy-dandy canned routines that ship with MATLAB are actually quite limited when it comes to customizability. Whenever you have some file writing to do with a custom format, it comes in handy to know how to do it yourself:
% Open file for writing, safely
fid = fopen(fullfile('e:\temp\', str, '.txt'), 'w');
OC = onCleanup(#() any(fopen('all')==fid) && fclose(fid));
% Simply loop through all rows
for ii = 1:size(temp,1)
% Format the numbers, with comma as separator
line = sprintf('%.10f,', temp(ii,:)); % (trick to concatenate last dimension into second one)
line(end) = []; %(remove last comma)
% Print this line, adding two PC-type newlines
fprintf(fid, '%s\r\n\r\n', line);
end
% Clean up
fclose(fid);

Related

Saving a string array to CSV

I have a 25194081x2 matrix of strings called s1. Below an outlook of how the data looks like.
I am trying to save this matrix to csv. I tried the code below but for some reason it saves the first column of the vector twice (side by side) instead of the two columns.
What am I doing wrong?
fileID= fopen('data.csv', 'w') ;
fprintf(fileID, '%s,%s\n', [s1(:,1) s1(:,2)]);
fclose(fileID)
Dont merge the columns to a string array like you do now, but provide them as separate arguments, and loop over the rows of s1:
fileID= fopen('data.csv', 'w') ;
for k = 1:size(s1,1)
fprintf(fileID, '%s,%s\n', s1(k,1), s1(k,2));
end
fclose(fileID)
Or, if you're using >R2019a, you can use writematrix:
writematrix(s1, 'data.csv');
My version of MATLAB (R2016a) does not have the string type available yet, but your problem is one I was having regularly with cell arrays of character vectors. The trick I was using to avoid using a loop for fprintf should be applicable to you.
Let's start with sample data as close to yours:
s1 = {'2F5E8693E','al1 1aj_25';
'3F5E8693E','al1 1aj_50';
'3F5E8693E','al1 1aj_50';}
Then this code usually executed much faster for me than having to loop on the matrix for writing to file:
% step 1: transpose, to get the matrix in the MATLAB default column major order
s = s1.' ;
% step 2 : Write all in a long character array
so = sprintf('%s, %s\n', s{:} ) ;
% step 3 : write to file in one go (no need loop)
fid = fopen('data.csv', 'w') ;
fprintf(fid,'%c',so) ;
fclose(fid) ;
The only step slightly different for you might be step 2. I don't know if this syntax will work on a matrix of string as good on a cell array of characters, but I'm sure there is a way to get the same result: a single long vector of characters. Once you get that, fprintf will be uber fast to write it to file.
note: If the amount of data is too large and with a limited memory you might not be able to generate the long char vector. In my experience, it was still faster to use this method in chuncks (which would fit in memory) rather than looping over each line of the matrix.

How to ignore header in text file when reading it

I am trying to read a text file and store the data inside into structs and I am interested in finding out how to ignore the first 4 lines (text header) in the text file.
This is the text file:
text file
I am only going to need the numeric values from it (year int, month int, max double, etc.) and ignore the four text lines above them.
This is the code I use to store the values as a collection of structs:
code
You can use func dropFirst(_ n: Int) to skip initial lines:
let lines = contents.components(separatedBy: "\n")
for line in lines.dropFirst(4) {
// ...
}
dropFirst(4) returns an “array slice” with all but the first 4
elements in the lines array, which means that the element storage
is not duplicated.
If it's always 4 lines then #Martin R has a good answer, otherwise you could see if the first word can be converted to an int like
for line in filtered {
let x = line.components(separatedBy: " ")
guard let year = Int(x[0] else {
continue
}
....

Matlab: concatenation of 'n' vectors with data from 'n' .csv files within a loop. To show in a structure or table

I know there are a lot of posts about concatenation of arrays, but I can't find one that I can use for my case.
I have the following code, that reads a .csv file with mixed data types (using this function), and can store the elements of one .csv file into a Vector of dimensions Nx1.
basepath = 'Unzipped\Portfolio';
files = dir(fullfile(basepath, '*.csv'));
% Pre-allocate data storage
data = cell(size(files));
N=0;
% Import each file using it's filename
for k = 1:numel(files)
data{k} = csvimport(fullfile(basepath, files(k).name)); %reads all the data
[a, b]=size(data{k}); %the size of our data matrix
Index{k}=a-1; %Size of one .csv
N=N+Index{k}; %Size of all .csv
%for single .csv
V1s{k}=cell(Index{k}, 1);
V2s{k}=cell(Index{k}, 1);
V3s{k}=cell(Index{k}, 1);
V4s{k}=cell(Index{k}, 1);
%for all .csv
V1=cell(N,1);
V2=cell(N,1);
V3=cell(N,1);
V4=cell(N,1);
end
for i = 1:numel(files)
%Filling out every vector for a single .csv file and showing it up
[pathstr,name,ext] = fileparts(files(i).name);
V4s{i}(1:Index{i},1)=cellstr(name); %this vector contains only the name of the file repeatedly
V1s{i}=data{i}(2:end, 15);
V2s{i}=data{i}(2:end, 14);
V3s{i}=data{i}(2:end, 9);
C{i}=[V4s{i} V1s{i} V2s{i} V3s{i}] ;
Table{i}=array2table(C{i}, 'VariableNames', {'V1s' 'V2s' 'V3s' 'V4s'});
%For all .csv's
%This is where my doubts are and I know this one won't produce me any results.
V4=cat(1,V4s{:});
end
My problem comes when I have to make the concatenation of all the vectors one by one. It would be simple if I had, let's say, 3 of 'em.
I could use something like C=[V1; V2; V3]. But I can't find a way to make them all do that.
I was thinking about using counters and start indexing for every i, something like this:
V1(a:b,1)=V1s{i}
With values a and b being counter. But I don't how to write them.
I want a massive vector Nx1 with all of the V{i} going right after the next set of values.
Any help will be appreciated.
If you use the {:} operator, it will expand all of the contents of the cell array as input arguments. So if we call cat with the input data as a cell array, we can do the following to achieve what you want.
V1 = cat(1, V1s{:});
This is effectively the same as doing
V1 = [V1s{1}; V1s{2}; V1s{3}, ..., V1s{n}]
If I understood your question correctly (to read multiple csv files and store them into a N x 1 vector):
C = []; //start with an empty vector
for ... //for each csv file
M = csvread(filename); //read the csv file into a matrix
V = reshape(M, [numel(M) 1]); //reshape the matrix into an nx1 vector
C = vertcat(C, V); //concatenate nx1 vectors into Nx1 vectors
end
There are multiple ways to loop through your csv files. Either loop through an array of filenames, or you can obtain all the .csv files in the directory with:
files = dir('*.csv');
and loop through the csv files like that:
for i=1:length(files)
filename = files(i).name;
...
end
I had to work on an 'alternative' solution. I'm sure there's an easier way. But I'll settle with this one just for now.
I tried this approach: Indexing with counters. For that, you have to define those counters. So, for every different V{i}, you can index those values within a certain range.
To understand this in a better way, you have to add the following part to the last loop in my code above. Obviously, you must say first that counters are equal to zero outside of the loop so it can take an effect.
m=m+Index{i};
n=m-Index{i}+1;
V4(n:m,1)=V4s{i};
Remember, you have to place it below the commentary line that says
% For all .csv's
% This is where my doubts are and I know this one won't produce me any results.
And initialize m and n before getting into the loop:
m=0;
n=0;
You can apply this approach for indexing really large vectors or concatenating several of them.

matlab readfile with numbers

In general I'm defining a matlab fnction which takes the name of a file containing some numbers, one per line, reads the data in, and then returns the data in an array.
function x = readdata(filename)
This function takes the name of a file contained in the
% character array "filename", read in the data from it, and then
% return the resulting numbers in the 1-dimensional array x. The
% array x can be n x 1 or 1 x n, where n is the number of numbers
% in the data file.
%
% If the data file cannot be found, this function should print a
% warning (using the disp() function) and return x as an empty
% array. If the data file can be found but is empty or contains
% only comments (lines starting with the Matlab comment indicator %),
% this function should return an empty array x with no warning
% message.
%
%
%I'm not sure how to check if a file exist (while they are in same folder).
%I tried if exist(filename,'file') but this is not working
This is what I have now:
function x = readdata(file)
fid = fopen(file);
tline = fgets(fid);
while isnumeric(tline)
disp(tline)
tline = fgets(fid)
Thanks
I would start by taking a look at the documentation that you could find here for reading in line-by-line. It even gives a sample code that you could start with:
Reading Data Line-by-Line
MATLAB provides two functions that read lines from files and store them in
string vectors: fgetl and fgets. The fgets function copies the newline
character to the output string, but fgetl does not.
The following example uses fgetl to read an entire file one line at a time.
The function litcount determines whether an input literal string (literal)
appears in each line. If it does, the function prints the entire line preceded
by the number of times the literal string appears on the line.
function y = litcount(filename, literal)
% Search for number of string matches per line.
fid = fopen(filename);
y = 0;
tline = fgetl(fid);
while ischar(tline)
matches = strfind(tline, literal);
num = length(matches);
if num > 0
y = y + num;
fprintf(1,'%d:%s\n',num,tline);
end
tline = fgetl(fid);
end
fclose(fid);
You should be able to replace what is inside the while loop with what you are looking to do.
Of note is that the fgets and fgetl functions return character arrays (strings). Thus, you'll need to first check whether the line is a comment, and then, if not, convert the string to a numeric value using something along the lines of str2double.
As for checking existence of a file, exist(filename,'file') is definitely what you want. Its documentation is found here.
You should be able to do something like:
if ~exist(filename,'file')
% Do something... I suggest the warning function, disp could be used too...
warning('The file cannot be found!')
return
end

How to get matlab to read a txt file with image names and populate an array?

My objective here is to read from a text file filenames for images as strings, EX: myImage.jpg.
I have this block of code that reads how many lines are in the file.
listOfImages = fopen('translate.txt', 'r');
count = 0;
%This while loop calculates the amount of lines within our text file
while ~feof(listOfImages)
line = fgetl(listOfImages);
if isempty(line) | strncmp(line, '%', 1)
continue
end
count = count+1;
end
numberOfLines = count;
now using numberOfLines how do i put each line into some sort of array of strings using a for loop.
so,
for i = 1:numberOfLines,
DO CODE
end
what do i put here to make it so i can read my translate.txt file row by row?
thanks
Because the file names will likely be different lengths you will want to use a cell instead of a matrix.
Try the following:
% read the text into names, breaking on newlines
fid = fopen('translate.txt');
names = textscan(fid,'%s','delimiter','\n');
names = names{1};
fclose(fid);
for f = 1:length(names)
disp(names(f));
end

Resources