Formatting cell to double - matlab

I have text file in which the data is like (1,2),(3,4),1 (4,5),(6,7),1
I am reading the file in the matlab as:
A= textread('abc.txt', '%s');
the output is
A: 2x1 cell
(1,2),(3,4),1
(4,5),(6,7),1
Anyone please help to convert this cell to double with the output
New_A= 5x2 double
1 2 3 4 1
4 5 6 7 1

For your particular example, once you read the file, you can use textscan.
A = {'(1,2),(3,4),1'
'(4,5),(6,7),1'};
New_A = cell2mat(cellfun(#(line) cell2mat(textscan(line,'(%f,%f),(%f,%f),%f')), A, 'UniformOutput', 0));
New_A =
1 2 3 4 1
4 5 6 7 1
You can also do similar, line by line, as they are read from the file.

This can be done using regexprep, cell2mat and str2num as follows:
A = {'(1,2),(3,4),1'
'(4,5),(6,7),1'}; % This is what you get after this: A= textread('abc.txt', '%s');
New_A = regexprep(A,'(\(|\))',''); %Removing the brackets ()
New_A = str2num(cell2mat(New_A)) %Converting char cell to numeric matrix

Related

How to read numbers in file and put them into multiple arrays based on separator?

Data sample:
1
2
3
-
4
5
-
6
7
8
I have a file with one number per line and there is a separator. How can I get an array like that:
output = [[1,2,3], [4,5], [6,7,8]]
Thanks
Read the file contents into int vector fscanf(fid,'%d',[1 inf]) and skip one string fscanf(fid,'%s', 1), then continue reading a vector and one string until end-of-file.
out = {};
fid = fopen('file.txt');
while ~feof(fid)
out{end+1:end+1} = fscanf(fid,'%d',[1 inf]);
fscanf(fid,'%s', 1);
end
fclose(fid);
out =
1×3 cell array
{[1 2 3]} {[4 5]} {[6 7 8]}

Matlab from text file to sparse matrix.

I have a huge text file in the following format:
1 2
1 3
1 10
1 11
1 20
1 376
1 665255
2 4
2 126
2 134
2 242
2 247
First column is the x coordinate while second column is the y coordinate.
It indicates that if I had to construct a Matrix
M = zeros(N, N);
M(1, 2) = 1;
M(1, 3) = 1;
.
.
M(2, 247) = 1;
This text file is huge and can't be brought to main memory at once. I must read it line by line. And save it in a sparse matrix.
So I need the following function:
function mat = generate( path )
fid = fopen(path);
tline = fgetl(fid);
% initialize an empty sparse matrix. (I know I assigned Mat(1, 1) = 1)
mat = sparse(1);
while ischar(tline)
tline = fgetl(fid);
if ischar(tline)
C = strsplit(tline);
end
mat(C{1}, C{2}) = 1;
end
fclose(fid);
end
But unfortunately besides the first row it just puts trash in my sparse mat.
Demo:
1 7
1 9
2 4
2 9
If I print the sparse mat I get:
(1,1) 1
(50,52) 1
(49,57) 1
(50,57) 1
Any suggestions ?
Fixing what you have...
Your problem is that C is a cell array of characters, not numbers. You need to convert the strings you read from the file into integer values. Instead of strsplit you can use functions like str2num and str2double. Since tline is a space-delimited character array of integers in this case, str2num is the easiest to use to compute C:
C = str2num(tline);
Then you just index C like an array instead of a cell array:
mat(C(1), C(2)) = 1;
Extra tidbit: If you were wondering how your demo code still worked even though C contained characters, it's because MATLAB has a tendency to automatically convert variables to the correct type for certain operations. In this case, the characters were converted to their double ASCII code equivalents: '1' became 49, '2' became 50, etc. Then it used these as indices into mat.
A simpler alternative...
You don't even have to bother with all that mess above, since you can replace your entire function with a much simpler approach using dlmread and sparse like so:
data = dlmread(filePath);
mat = sparse(data(:, 1), data(:, 2), 1);
clear data; % Save yourself some memory if you don't need it any more

Adding time slice in a matlab output using fprintf

I have matlab output of a complex number, where 'modTrace' contains the complex numbers. to write my output in a file called '3pt.txt' I write the following:
modTrace
fileID = fopen('3pt.txt','w');
fprintf ( fileID,'%e+%ei\n',real ( traces ), imag ( traces ) );
fclose(fileID);
The output looks like this:
2.355387e-13+3.263411e-12i
3.037095e-12+1.848502e-12i
2.264321e-12+1.408536e-12i
3.808791e-13-1.647224e-14i
-3.249665e-14+7.954636e-15i
7.026766e-14+1.056313e-13i
and so on. Now if I want the output with time slice numbers to the left, something like:
0 2.355387e-13+3.263411e-12i
1 3.037095e-12+1.848502e-12i
2 2.264321e-12+1.408536e-12i
3 3.808791e-13-1.647224e-14i
4 -3.249665e-14+7.954636e-15i
5 7.026766e-14+1.056313e-13i
and so on, how to I edit the code?
Thank you in advance for help.
Your fprintf statement is not working the way you are intending. It prints out all the values in real(traces) before getting to imag(traces). For example,
>> v = [1 2; 3 4; 5 6]
v =
1 2
3 4
5 6
>> fprintf('%d %d\n',v(:,1),v(:,2))
1 3
5 2
4 6
To pair values the way intended, you need to transpose the matrix:
>> fprintf('%d %d\n',v.')
1 2
3 4
5 6
Following this example, you can prepend slice numbers as follows:
v = [(1:numel(traces)).' real(traces(:)) imag(traces(:))].';
fprintf(fileID,'%d %e+%ei\n',v)

Using Matlab to make modification to a text file

Essentially I am writing a Matlab file to change the 2nd, 3rd and 4th numbers in the line below "STR" and above "CON" in the text file (which is given below and is called '0.dat'). Currently, my Matlab code makes no changes to the text file.
Text File
pri
3
len 0.03
vic 5 5
MAT
1 147E9 0.3 0 4.9E9 8.5E9
LAY
1 0.000125 1 45
2 0.000125 1 0
3 0.000125 1 -45
4 0.000125 1 90
5 0.000125 1 45
WAL
1 1 2 3 4 5
PLATE
1 0.005 1 1
STR
1 32217.442335442 3010.34241024889 2689.48842888812
CON
1 2 1 2 3 1 3 4 1 4 5 1 5 6 1 6 7 1
ATT
1 901 7 901
LON
34
POI
123456
1 7
X 0.015
123456
2 6
X 0.00381966011250105 0.026180339887499
123456
3 5
X 0.000857864376269049 0.0291421356237309
123456
4
X 0
PLO
2 3
CRO
0
RES
INMOD=1
END
Matlab code:
impafp = importdata('0.dat','\t');
afp = impafp.textdata;
fileID = fopen('0.dat','r+');
for i = 1:length(afp)
if (strncmpi(afp{i},'con',3))
newNx = 100;
newNxy = 50;
newNy = 500;
myformat = '%0.6f %0.9f %0.9f %0.9f\n';
newData = [1 newNx newNxy newNy];
afp{i-1} = fprintf(fileID, myformat, newData);
fclose(fileID);
end
end
From the help for importdata:
For ASCII files and spreadsheets, importdata expects to find numeric
data in a rectangular form (that is, like a matrix). Text headers can
appear above or to the left of numeric data. To import ASCII files
with numeric characters anywhere else, including columns of character
data or formatted dates or times, use TEXTSCAN instead of import data.
Indeed, if you print out the value of afp, you'll see that it just contains the first line. You were also not performing any operation that was writing to a file. And you were not closing the file ID if the if state wasn't triggered.
Here is one way to do this with textscan (which is probably faster too):
% Read in data as strings using textscan
fid = fopen('0.dat','r');
afp = textscan(fid,'%s','Delimiter','');
fclose(fid);
isSTR = strncmpi(afp{:},'str',3); % True for all lines starting with STR
isCON = strncmpi(afp{:},'con',3); % True for all lines starting with CON
% Find indices to replace - create logical indices
% True if line before is STR and line after is CON
% Offset isSTR and isCON by 2 elements in opposite directions to align
% Use & to perform vectorized AND
% Pad with FALSE on either side to make output the same length as afp{1}{:}
datIDX = [false;(isSTR(1:end-2)&isCON(3:end));false];
% Overwrite data using sprintf
myformat = '%0.6f %0.9f %0.9f %0.9f';
newNx = 100;
newNxy = 50;
newNy = 500;
newData = [1 newNx newNxy newNy];
afp{1}{datIDX} = sprintf(myformat, newData); % Set only elements that pass test
% Overwrite old file using fprintf (or change filename to new one)
fid = fopen('0.dat','w');
fprintf(fid,'%s\r\n',afp{1}{1:end-1});
fprintf(fid,'%s',afp{1}{end}); % Avoid blank line at end
fclose(fid);
If you're unfamiliar with logical indexing, you might read this blog post and this.
I would recommend just reading the entire file in, finding which lines contain your "keywords", modifying specific lines, and then writing it back out to a file, which can have the same name or a different one.
file = fileread('file.dat');
parts = regexp(file,'\n','split');
startIndex = find(~cellfun('isempty',regexp(parts,'STR')));
endIndex = find(~cellfun('isempty',regexp(parts,'CON')));
ind2Change = startIndex+1:endIndex-1;
tempCell{1} = sprintf('%0.6f %0.9f %0.9f %0.9f',[1,100,50,500]);
parts(ind2Change) = deal(tempCell);
out = sprintf('%s\n',parts{:});
out = out(1:end-1);
fh = fopen('file2.dat','w');
fwrite(fh,out);
fclose(fh);

How to display sequence numbers in Matlab in a better way?

For example, I have an array:
a=[1:5 8:10];
If I display it using:
disp(['a = ' num2str(a)]);
The result would be something like
a = 1 2 3 4 5 8 9 10
It's quite too long than I need. How can I let Matlab to display as same as the way I defined it or as close as is?
Be more specific, if I defined the variable in an "informal" way like:
a=[1:3 4:6 8:10]
(should be normally 1:6 instead of 1:3 4:6)
I just want Matlab to display in either way:
1:3 4:6 8:10 or 1:6 8:10
I also not care about whether it displays the variable name or square brackets.
Searched but didn't find anything useful. Considered to manually parse it but doesn't sounds like a clever way.
Any suggestion would be great helpful, thanks a lot.
The only way to do this would be to create your own function to display the arrays in the format you want. For example, if you want to display monotonically-increasing portions of your array in a condensed fashion, you could use a function like this:
function display_array(array)
str = cellfun(#(n) {num2str(n)}, num2cell(array));
index = (diff(array) == 1) & ([1 diff(array, 2)] == 0);
str(index) = {':'};
str = regexprep(sprintf(' %s', str{:}), '( :)+\s*', ':');
disp([inputname(1) ' = [' str(2:end) ']']);
end
And you would use it like so:
>> a = [1:5 7 9:11] %# Define a sample array
a =
1 2 3 4 5 7 9 10 11 %# Default display
>> display_array(a)
a = [1:5 7 9:11] %# Condensed display
>> b = [1 2 3 4 4 4 3 2 1]; %# Another sample array
>> display_array(b)
b = [1:4 4 4 3 2 1] %# Note only the monotonically increasing part is replaced
For this, I use vec2str from the Matlab file exchange. For example:
str = vec2str([1 3 5 5 9 8 7 6 5])
ans =
[1:2:5,5,9:-1:5]
>> eval(str)
ans =
1 3 5 5 9 8 7 6 5
Impossible. Matlab throws away your definition very quickly. The "object" a has no knowledge of that definition at all.