Using importdata() to automatically change headerlines from file to file - matlab

Okay so I have multiple files that I'm trying to import for analysis, and I'm using uiimport() to do this within a script currently, but I have to manually shift the headerlines for each file as they change every time. I would like to do something like this:
DELIMITER = ',';
HEADERLINES = 50;
data_imported = importdata(file_to_get, DELIMITER, HEADERLINES);
But the issue is that only 1 or 2 of my 300~ files has a headerline count of 50. Another very important note, is that the default number of headerlines for EVERY file only needs to have 2 added to it. So if the default headerline number while using uiimport() is 50, then i would need to change it to 52.
Would there be a way to change this with possibly an if statement? Note: defaultheader is being used as and example and not an actual variable.
for example:
if defaultheader = 30
header = 32
end
example of what the .CSV file looks like in excel
*Title
*
*Description (1.7) Tue 03/20/12 09:59:09
*
* file name
*
* TestNames:
* _Test 1 (ein: 10)
* _Test 2 (ein: 15)
* _Test 3 (ein: 20)
* _Test 4 (ein: 25)
* _test 5 (ein: 30)
* _test 6 (ein: 35)
* _test 7 (ein: 40)
* _test 8 (ein: 45)
* _test 9 (ein: 50)
* _test 10 (ein: 55)
* _test 11 (ein: 60)
* _test 12 (ein: 65)
* _test 13 (ein: 70)
* _test 14 (ein: 75)
* _test 15 (ein: 80)
* _test 16 (ein: 85)
*
* Info1: ...
* Info2: ...
* info3: ...
* info4: ...
* info5: ...
* info6: ...
* info7: ...
* info8: ...
* info9: ...
* info10: ...
* info11: ...
* info12: ...
*
* Pixel,Tap Name,Tap Pixel,brightness
,,,10,15,20,25,30,35,40
,,,0,67,21,12,223,231,832
1,0A1,458,75,89,24,46,256,763,532
2,0A1,457,43,65,56,554,263,254,732
3,0A1,456,28,47,76,221,412,732,832
4,0A1,455,12,23,36,466,652,633,637
5,0A1,454,11,78,98,678,864,241,223

You could use TEXTSCAN function to read the CSV files, and specify the CommentStyle option to ignore all header lines starting with a * character.
The code below will first read the file as a cell array of lines, ignoring all lines starting with *. We also skip the first two lines immediately after the header section. Next, we loop over each line, and parse the tab-delimited values as string. We ignore the first three columns, and convert the remaining values to numeric. Finally we store that row in the matrix M. Note that the code does not assume we know the number of columns in advance, and instead determine that from one of the data rows.
%# read lines
fid = fopen('file.csv','rt');
C = textscan(fid, '%s', ...
'Delimiter','', 'Whitespace','\n', 'CommentStyle','*');
fclose(fid);
C = C{1}(3:end); %# skip two lines
%# parse each line
numCols = sum(C{1}==',')+1 - 3; %# number of columns
M = zeros(numel(C),numCols);
for i=1:numel(C)
v = textscan(C{i}, '%s', 'Delimiter',',');
v = str2double(v{1}(4:end));
M(i,1:numel(v)) = v;
end
The resulting matrix M containing the part of the file you are interested in:
M =
75 89 24 46 256 763 532
43 65 56 554 263 254 732
28 47 76 221 412 732 832
12 23 36 466 652 633 637
11 78 98 678 864 241 223

Related

MATLAB write string and then table to file

I need to write a string and a table to one text file. The string contains a description of the data in the table, but is not the headers for the table. I am using R2019a which I guess means the "Append" writetable option does not work? Please see my example data below:
% Load data
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
string = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
% How I tried to do this (which does not work!)
fid = fopen(filename, 'w', 'n');
fprintf(fid, '%s', cell2mat(string))
fclose(fid);
writetable(table, filename, 'FileType', 'text', 'WriteVariableNames', 0, 'Delimiter', 'tab', 'WriteMode', 'Append')
I get this error:
Error using writetable (line 155)
Wrong number of arguments.
Does anyone have a suggestion as to how to proceed?
Thanks!
A bit hacky, but here's an idea.
Convert your existing table to a cell array with table2cell.
Prepend a row of cells which consists of your string, followed by empty cells.
Convert the cell array back to a table with cell2table, and write the new table to the file.
load cereal.mat;
table = table(Calories, Carbo, Cups, Fat, Fiber, Mfg, Name, Potass);
s = {'This is a string about the cereal table'};
filename = "dummyoutput.sfc";
new_table = cell2table([[s repmat({''},1,size(table,2)-1)] ; table2cell(table)]);
writetable(new_table,filename,'FileType','text','WriteVariableNames',0,'Delimiter','tab');
>> !head dummyoutput.sfc
This is a string about the cereal table
70 5 0.33 1 10 N 100% Bran 280
120 8 -1 5 2 Q 100% Natural Bran 135
70 7 0.33 1 9 K All-Bran 320
50 8 0.5 0 14 K All-Bran with Extra Fiber 330
110 14 0.75 2 1 R Almond Delight -1
110 10.5 0.75 2 1.5 G Apple Cinnamon Cheerios 70
110 11 1 0 1 K Apple Jacks 30
130 18 0.75 2 2 G Basic 4 100
90 15 0.67 1 4 R Bran Chex 125

MATLAB create constant spacing between numbers on same line

Good morning,
I'm sure there's a built in function but I can't find it. I want to create static positioning for information being sent to a text document in MATLAB. For example:
height weight age favorite number
------------------------------------------------------------
60 140 24 9
30 45 3 10000000
48 100 9 19
9 7 1 1
currently, i'm just doing an fprint call with padded spaces to get it lined up, but the issue arises where having different length numbers causes the alignment to be off, like so:
height weight age favorite number
------------------------------------------------------------
60 140 24 9
30 45 3 10000000
48 100 9 19
1 7 1 1
Thanks in advance.
here's an example script that'll show what I mean:
fid1 = fopen('stackoverflowtest', 'w');
if fid1 < 3,
error('ERROR');
end;
fprintf(fid1, 'height weight age favorite number \n');
fprintf(fid1, '------------------------------------------------------------ \n');
height = 0;
weight = 10;
age = 100;
number = 3;
for i = 1:100
fprintf(fid1, "%d ', height);
fprintf(fid1, "%d ', weight);
fprintf(fid1, "%d ', age);
fprintf(fid1, "%d \n", number);
height = height + 3;
weight = weight + 6;
age = age - 1;
number = number + 23;
end
You can do this with the fprintf format specification, for example %-15d.
Here, the - is a flag which specifies left justification, and the 15 specifies how much space to leave around the representation.
We can reproduce your example with
A = [60 140 24 9
30 45 3 10000000
48 100 9 19
9 7 1 1];
fprintf('height weight age favorite number \n'),...
fprintf('------------------------------------------------------------ \n'),...
fprintf('%-15d %-15d %-12d %-15d \n',A')
which displays
height weight age favorite number
------------------------------------------------------------
60 140 24 9
30 45 3 10000000
48 100 9 19
9 7 1 1
EDIT: You can store this data as a table:
height = A(:,1)
weight = A(:,2);
age = A(:,3);
favourite_number = A(:,4);
tab1 = table(height, weight, age, favourite_number);
disp(tab1);
This prints to screen
height weight age favourite_number
______ ______ ___ ________________
60 140 24 9
30 45 3 1e+07
48 100 9 19
9 7 1 1
but I'm not sure how to save this representation to a file.

Matlab Date Vector

I have an array A with time information in the format hhmmss. Ultimately, I would like to normalize this array by indicating the elapsed time (in seconds, starting from the first time).
A = [ 150213
150013
145813
145613
145413
145313
145213
145113
145013
144943
144913
144843
144833
144823
144813
144803
144753
144743
144741
144739
144737
144735
144733
144731
144729
144727
144725
144723
144721
144719]
So, in the end the array should be :
A_updated = [894
774
654
534
414
354
294
234
174
144
114
84
74
64
54
44
34
24
22
20
18
16
14
12
10
8
6
4
2
0
]
What would be the quickest 'Matlab way' to proceed with this? Many thanks in advance for your ideas.
I haven't used Matlab in a while, so forgive the syntax mistakes, and I don't have it available right now, but here's what I would try. Basically, convert everything to seconds then subtract the last element.
At = uint32(A);
A_updated = mod(At,100);
At = floor(At ./ 100);
A_updated = A_updated + mod(At,100) * 60;
At = floor(At ./ 100);
A_updated = A_updated + At * 3600;
A_updated = A_updated - A_updated(end);
I did this in Octave so you may need to adjust the syntax for datenum:
B = double(A);
hh = floor(B/10000);
mm = floor((B-hh*10000)/100);
ss = B - hh*10000 - mm*100;
C = datenum(2013,10,28,hh,mm,ss);
elapsed_time = (C-C(end))*3600*24;

Reading a text file as a input and then writing text files with the data in 2D matrices as output

I am the real novice in FORTRAN90, of course in any other programming language.
However, I need to make a program for my work.
So I am asking any comment from anybody.
Thanks in advance.
From now on, I will explain my problem.
The original data is just following as;
15 1r 2 1r 70 22r 2 2r 15 1r 2 1r 8 8r 15 1 3r
This is could be written again in another way like below;
15 15 2 2 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 70 2 2 2 15 15 2 2
8 8 8 8 8 8 8 8 8 15 1 1 1 1
So the total number of data elements in the above example can be counted 48.
The total number of the original data is 12,113,640.
And then the original data was made of 220(z) slices of 322(x) x 171(y).
Each slices has 55,062 of elements.
If it is possible, just like the way of count of the element number, the program count by 55,062 elements and then make output file(txt) and then totally 220 slices of the data should be 2D array.
So I have to extract 220 slices from the one whole data file. And also the data should be 2D array in each slice.
It will be something like this - I assume you know how to read lines from the file
program main
character(len=120):: compressed
character ch
integer value, rval, repeat, ix, complen
! Pretend this is the line read from the file
compressed = '15 1r 2 1r 70 22r 2 2r 15 1r 2 1r 8 8r 15 1 3r'
complen = len(trim(compressed))
ix = 1
do while (ix .lt. complen)
! Skip spaces
do
ch = compressed(ix:ix)
if (ch .ne. ' ') exit
ix = ix + 1
end do
! Extract the number
value = 0
do
ch = compressed(ix:ix)
if (ch .ge. '0' .and. ch .le. '9') then
value = value * 10 + ichar(ch) - ichar('0')
else
exit
end if
ix = ix + 1
if (ix .gt. complen) exit
end do
! is it a repeater
repeat = 1
if (ch .eq. 'r') then
! reduce by 1 since one has already been printed
repeat = value - 1
ix = ix + 1
else
rval = value
end if
! assume there won't be more than 100 repeats
write(*, '(100I3)', advance='no') (rval, ii = 1, repeat)
end do
stop
end program

Coffeescript: conditional value one-liner

Can this be turned into a snazzy one-liner?
thing = thing2 / 32 * 100 * 100
thing = 0 unless thing
Unfortunately coffeescript doesn't support ternary operator. But you can write:
#zoomGlobal = if #position.ratio then #position.ratio / 32 * 100 * 100 else 0
Or
#zoomGlobal = #position.ratio / 32 * 100 * 100 || #zoomGlobal
Here example
if you are confident that #position.ratio is always set as a number, you could just have:
#zoomGlobal = #position.ration / 32 * 100 * 100
soon you should be able to use the new ** operator
#zoomGlobal = #position.ration / 32 * 100 ** 2
if #position.ration might not exist then use what Ivan suggested:
#zoomGlobal = if #position.ratio then #position.ratio / 32 * 100 * 100 else 0
also, I can't see from your example what the context is but note that
10 / 2 * 2 * 2 == 20
while
10 / (2 * 2 * 2) == 1.25