Reading a .dat file into MATLAB variables - matlab

I've used neworkx to generate a random geometric graph on 50 nodes, and create a .dat file with some attributes of this network.
I need to access these as MATLAB variables. I read the file in as a data string using:
fid = fopen('mydata.dat','r')
data = textscan(fid, '%s')
fclose(fid)
The structure of the data file is as follows
conn = val
Adj = val ..... val
.............
val ......val
pos =
[0.7910629988376467, 0.5523474928588686]
...
[0.6799716933198028, 0.6981655240935597]
i.e. conn is a number, Adj is (supposed to be) a 50 by 50 matrix and pos is a 50 by 2 matrix.
I can read conn, and Adj as MATLAB variables fine, but I'm having trouble reading pos. The first instance starts at data{1}{2508}, and is
data{1}{2508}
>>> [0.7832623541518583,
How do I shoehorn this into a 50 by 2 (or 2 by 50) matrix?
To read the Adj I use
P = 50 %number of nodes
index = 5
for i=1:P
for j = 1:P
Adj(i,j) = str2double(data{1}(index + P*(i-1) +j))
end
end
I thought something similar would work for pos, but with j = 1:2 and index = 2508 but I'm getting NaNs as the lines (fields?) of my .dat file aren't just values, they're of the form [val, or ,val]

You can first delete all characters you don't want to have.
data = regexprep(data{1},'[\[\],]','');
After that, your loop should succeed. However, you can speed up your code by using array functions.
Find the occurance of pos
ind = find(strcmp(data,'pos')); # Should be 2506 in your case
After that, once you know that your array is 50x2 use:
pos = str2double(reshape(data(pos+2:end),2,50)')
Note, the +2 is for pos and =.

Related

Save matrices of a loop iteration in one matrix

I have a loop that makes a 100x10 matrix in every iteration, i want to save all the matrices of this loop in one matrix. assuming that i have a loop with 5 iterations, i want to have a 500x10 matrix in the end (after appending all the 5 matrices of the loop).
for ii = 1:numfiles
str = fullfile(PathName,FileName{ii});
file_id = fopen(str);
data = fread (file_id)';
....
s = zeros (100, 10);
%doing some stuffs
save('s_all', 's','-append');
end
I have used save('s_all', 's','-append');
but it doesn't append the matrices. How can i do that?
As you can read in the document:
save(filename,variables,'-append') adds new variables to an existing file. If a variable already exists in a MAT-file, then save overwrites it with the value in the workspace.
Therefore, save just adds a variable at the end of the .mat file, not to add at the end of a variable inside the .mat file.
Solution 1:
To write matrix into the file it would be better using dlmwrite likes the following:
dlmwrite(filename,s,'-append');
You can find more details here.
In a complete case you can do:
filename = 's_all.csv';
for ii = 1:numfiles
str = fullfile(PathName,FileName{ii});
file_id = fopen(str);
data = fread (file_id)';
% ...
s = zeros (100, 10);
%doing some stuffs
dlmwrite(filename,s,'-append');
end
Solution 2:
The other solution is each time load the specified matrix, then attach the matrices into it, and then append to the file.
filename = 'file.mat';
% suppose originMatrix is an empty matrix or a matrix with columns size 10
for ii = 1:numfiles
load(filename,'originMatrix');
s = zeros (100, 10);
%doing some stuffs
originMatrix = [originMatrix; s];
save(filename,'originMatrix','-append');
end

Fortran and Matlab: Change the data format

I have saved my job in Fortran with the following format
OPEN(50,file ='h.dat',form='formatted')
WRITE(50,'(101F12.6)')(u(k),k=1,nx)
CLOSE(50)
Since nx = 201, the data is saved in 2 lines. The first line has 101 columns, the second one has 100 columns. Therefore, MATLAB can not read h.dat with the following message “... must be the same as previous lines”.
Would it be possible to change this 2-line data to be 1-line data (201 columns) by using Matlab?
hh = importdata('h.dat');
size(hh) % ans = 2 101
nx = 201;
p = 0;
for i = 1:2;
for j = 1:101;
p = p+1;
ha(p) = hh(i,j);
end
end
ha = ha(1:nx);
save haa.dat ha -ascii
But, I think, it is much easier to use Fortran to solve it...

How to store .csv data and calculate average value in MATLAB

Can someone help me to understand how I can save in matlab a group of .csv files, select only the columns in which I am interested and get as output a final file in which I have the average value of the y columns and standard deviation of y axes? I am not so good in matlab and so I kindly ask if someone to help me to solve this question.
Here what I tried to do till now:
clear all;
clc;
which_column = 5;
dirstats = dir('*.csv');
col3Complete=0;
col4Complete=0;
for K = 1:length(dirstats)
[num,txt,raw] = xlsread(dirstats(K).name);
col3=num(:,3);
col4=num(:,4);
col3Complete=[col3Complete;col3];
col4Complete=[col4Complete;col4];
avgVal(K)=mean(col4(:));
end
col3Complete(1)=[];
col4Complete(1)=[];
%columnavg = mean(col4Complete);
%columnstd = std(col4Complete);
% xvals = 1 : size(columnavg,1);
% plot(xvals, columnavg, 'b-', xvals, columnavg-columnstd, 'r--', xvals, columnavg+columstd, 'r--');
B = reshape(col4Complete,[5000,K]);
m=mean(B,2);
C = reshape (col4Complete,[5000,K]);
S=std(C,0,2);
Now I know that I should compute mean and stdeviation inside for loop, using mean()function, but I am not sure how I can use it.
which_column = 5;
dirstats = dir('*.csv');
col3Complete=[]; % Initialise as empty matrix
col4Complete=[];
avgVal = zeros(length(dirstats),2); % initialise as columnvector
for K = 1:length(dirstats)
[num,txt,raw] = xlsread(dirstats(K).name);
col3=num(:,3);
col4=num(:,4);
col3Complete=[col3Complete;col3];
col4Complete=[col4Complete;col4];
avgVal(K,1)=mean(col4(:)); % 1st column contains mean
avgVal(K,2)=std(col4(:)); % 2nd column contains standard deviation
end
%columnavg = mean(col4Complete);
%columnstd = std(col4Complete);
% xvals = 1 : size(columnavg,1);
% plot(xvals, columnavg, 'b-', xvals, columnavg-columnstd, 'r--', xvals, columnavg+columstd, 'r--');
B = reshape(col4Complete,[5000,K]);
meanVals=mean(B,2);
I didn't change much, just initialised your arrays as empty arrays so you do not have to delete the first entry later on and made avgVal a column vector with the mean in column 1 and the standard deviation in column 1. You can of course add two columns if you want to collect those statistics for your 3rd column in the csv as well.
As a side note: xlsread is rather heavy for reading files, since Excel is horribly inefficient. If you want to read a structured file such as a csv, it's faster to use importdata.
Create some random matrix to store in a file with header:
A = rand(1e3,5);
out = fopen('output.csv','w');
fprintf(out,['ColumnA', '\t', 'ColumnB', '\t', 'ColumnC', '\t', 'ColumnD', '\t', 'ColumnE','\n']);
fclose(out);
dlmwrite('output.csv', A, 'delimiter','\t','-append');
Load it using csvread:
data = csvread('output.csv',1);
data now contains your five columns, without any headers.

Reading data from a Text File into Matlab array

I am having difficulty in reading data from a .txt file using Matlab.
I have to create a 200x128 dimension array in Matlab, using the data from the .txt file. This is a repetitive task, and needs automation.
Each row of the .txt file is a complex number of form a+ib, which is of form a[space]b. A sample of my text file :
Link to text file : Click Here
(0)
1.2 2.32222
2.12 3.113
.
.
.
3.2 2.22
(1)
4.4 3.4444
2.33 2.11
2.3 33.3
.
.
.
(2)
.
.
(3)
.
.
(199)
.
.
I have numbers of rows (X), inside the .txt file surrounded by brackets. My final matrix should be of size 200x128. After each (X), there are exactly 128 complex numbers.
Here is what I would do. First thing, delete the "(0)" types of lines from your text file (could even use a simple shells script for that). This I put into the file called post2.txt.
# First, load the text file into Matlab:
A = load('post2.txt');
# Create the imaginary numbers based on the two columns of data:
vals = A(:,1) + i*A(:,2);
# Then reshape the column of complex numbers into a matrix
mat = reshape(vals, [200,128]);
The mat will be a matrix of 200x128 complex data. Obviously at this point you can put a loop around this to do this multiple times.
Hope that helps.
You can read the data in using the following function:
function data = readData(aFilename, m,n)
% if no parameters were passed, use these as defaults:
if ~exist('aFilename', 'var')
m = 128;
n = 200;
aFilename = 'post.txt';
end
% init some stuff:
data= nan(n, m);
formatStr = [repmat('%f', 1, 2*m)];
% Read in the Data:
fid = fopen(aFilename);
for ind = 1:n
lineID = fgetl(fid);
dataLine = fscanf(fid, formatStr);
dataLineComplex = dataLine(1:2:end) + dataLine(2:2:end)*1i;
data(ind, :) = dataLineComplex;
end
fclose(fid);
(edit) This function can be improved by including the (1) parts in the format string and throwing them out:
function data = readData(aFilename, m,n)
% if no parameters were passed, use these as defaults:
if ~exist('aFilename', 'var')
m = 128;
n = 200;
aFilename = 'post.txt';
end
% init format stuff:
formatStr = ['(%*d)\n' repmat('%f%f\n', 1, m)];
% Read in the Data:
fid = fopen(aFilename);
data = fscanf(fid, formatStr);
data = data(1:2:end) + data(2:2:end)*1i;
data = reshape(data, n,m);
fclose(fid);

Matlab: read in part of binary data

I have a data set(binary file) which i want to read only the first half of X (and corresponding Y) data which is saved to 4D matrix:
for i = 1:vols
for j = 1:cols
XY(i,:,:,j) = fread(fid,[X Y],'int16');
end
end
How do I modify the above loop so only the first e.g. 10 X data (and corresponding Y) is read in for each vols and cols?
thanks
You will need to implement reading for each vols and cols in following order:
read part of Y for the first input X, than skip rest of this line, read part of Y for the second input X, etc.
After reading of requested number of X lines, you will need to skip rest of matrix before read next (vols, cols) pair.
To skip part of matrix you can use fseek function.
Let X_count and Y_cound are dimensions of submatrix; X_total and Y_total are dimension of total matrix. You need something like following:
for i = 1:vols
for j = 1:cols
for k=1:X_count
XY(i,k,:,j) = fread(fid,Y_count,'int16');
fseek(fid,(Y_total-Y_count)*2,'cof');
end
fseek(fid,(X_total-X_count)*Y_total*2,'cof');
end
end