The code below gives me error = Subscript indices must either be real positive integers or logicals.Because the first index using FIND function is i=1, the i-1 gives negative value. How to ignore when i==1 without using the LOOP function
fid=fopen('data.txt');
A=textscan(fid,'%f%f%f%f');
fclose(fid);
in = cell2mat(A);
i = find(in(1:end,2)>20 & in(1:end,2) <50);
out=in;
s(i)=sqrt((out(i,3)-out(i-1,3))*(out(i,3)-out(i-1,3))+(out(i,4)-out(i-1,4))*(out(i,4)-out(i-1,4)));
fid = fopen('newData.txt','wt');
format short g;
fprintf(fid,'%g\t%g\t%g\t%g\n',out',s'); %'# Write the data to the file
fclose(fid);
you can try something like this:
i = find(in(1:end,2)>20 & in(1:end,2) <50);
i = i(find( i > 1));
By the way, be careful of using i as a regular variable because you're overriding the default value of:
i = sqrt(-1)
Related
I'm new to MATLAB and I'm having problems printing a character array to a file. I only get the first character printed out. I read lines from a file and build an matrix of matrices. One matrix is an array of character vectors. Here's how I read the data
tline = fgetl(iin);
t_current = tline(9:34);
...
data.t = [data.t; t_current];
Then later I do this:
npts = length(data.t);
fid1 = fopen(fname, 'w');
fprintf(fid1, 'Day Rank\n');
fprintf(fid1, '------- -------\n');
for k = 1:npts
time_str = data.t(k);
fprintf(fid1, '%s %f3\n',time_str, data.rank(k));
end
fclose(fid1);
data.t is <10082,26 char> and looks something like this:
val =
2015-07-16T03:28:36.410305
2015-07-16T03:29:00.000000
...
All I get with the fprintf is a '2'. I tried to use convertCharsToStrings but that failed with an error message: Undefined function 'convertCharsToStrings' for input arguments of type
'char'.
This must be something simple I'm missing.
Thanks,
-Mike
Since "data.t is <10082,26 char>", try this:
...
for k = 1:npts
time_str = data.t(k, :);
...
If you do not use the , :, Matlab will use linear indexing for the matrix as opposed to subscripts.
It turns out I needed to use a different format for getting the time string:
time_str=data.t(k,1:end)
I need to read a text that has mix of numerical values and characters. Here is an example:
% Loc : LAT = -19.6423 LON = -70.817 DEP = 21.5451196625
I only need to read numerical fields.
Typically I used this:
x = fgetl(fid);
out = sscanf(x,'%% Loc : LAT = %f LON = %f DEP = %f\n');
It works but the problem is that not all the files have fixed format and sometimes letters are written in upper or lower cases. In such cases what I did does not work.
I tried skipping all characters using
out = sscanf(x,'%[a-zA-Z.=\t\b]s %f %[a-zA-Z.=\t\b]s %f %[a-zA-Z.=\t\b]s %f\n');
but it does not work!
Please note that file lines are not the same and I have different number of numerical field in each line of file.
I'm still a little unclear on your file format, but it seems like you could do this much easier using textscan instead of the lower level functions.
Something like this should work:
while (~feof(fid))
textscan(fid, '%s :'); % Read the part of the line through the colon
data = textscan(fid, '%s = %f');
% Do something with the data here
end
The variable fid is an file identifier that you would have to have gotten from calling fopen and you'll need to call fclose when you're done.
I don't think this is going to exactly fix your problem, but hopefully it will get you on a track that's much shorter and cleaner. You'll have to play with this to make sure that you actually get to the end of file, for example, and that there are not corner cases that trip up the pattern matching.
*scanf() uses a format string like "%d", not a multi-character constant like '%d'
Detail: " vs. '.
"%[] does not use a trailing 's' as OP used in '%[a-zA-Z.=\t\b]s'
"%n" records the int count of characters scanned so far.
Suggest
// Adjust these as needed
#define SKIPCHAR " %*[a-zA-Z.%:]"
#define EQUALFLOAT " =%f"
int n = 0;
float lat, lon, dep;
sscanf(x, SKIPCHAR EQUALFLOAT SKIPCHAR EQUALFLOAT SKIPCHAR EQUALFLOAT " %n",
&lat, &lon, &dep, &n);
if (n > 0 && x[n] == '\0') Success();
else Fail();
To cope with different number of numbers in a line:
#define XN 100
float x[XN];
char *p = x;
size_t i;
for (i=0; i<XN; i++) {
int n = 0;
sscanf(p, SKIPCHAR " %n", &n);
p += n;
n = 0;
sscanf(p, EQUALFLOAT " %n", &x[i], &n);
if (n == 0) break;
p += n;
}
I've found a possible solution even if it is for sure not "elegant", nevertheless seems working.
It is based on the following process:
read the file line by line using fgets
parse each string using strtok
try converting each token to a numebr with str2num
if it is actually a "number" str2num (i. e. if str2num does not returns an empty array) insert the number in the output matrix
The output matrix is initialized (to NaN) at the beginning of the script as big enough to have:
a number of rows greater or equal to the number of rows of the input file (if it is not known in advance, a "reasonable" value should be defined)
a number of columns greater or equal to the maximum number of numeric values that can be present in a row of the input file (if it is not known in advance, a "reasonable" value should be defined).
Once you've read all the input file, you can "clean" the the output matrix by removing the exceeding full NaN rows and columns.
In the following you can find the script, the input file I've used and the output matrix (looking at it should make more clear the reason for having initialized it to NaN - I hope).
Notice that the identification of the number and their extraction (using strtok) is based on the format of your the example row: in particular, for example, it is based on the fact that all the token of the string are separated by a space.
This means that the code is not able to identify =123.456 as number.
If your input file has token such as =123.456, the code has to be modified.
% Initialize rows counter
r_cnt=0;
% INitialize column counter
c_cnt=0;
% Define the number of rows of the input file (if it not known in advance,
% put a "reasonable" value) - Used to initialize the output matrix
file_rows=5;
% Define the number of numeric values to be extracted from the input file
% (if it not known in advance, put a "reasonable" value) - Used to
% initialize the output matrix
max_col=5;
% Initialize the variable holding the maximum number of column. Used to
% "clean" the output matrix
max_n_col=-1;
% Initialize the output matrix
m=nan(file_rows,max_col);
% Open the input file
fp=fopen('char_and_num.txt','rt');
% Get the first row
tline = fgets(fp);
% Loop to read line by line the input file
while ischar(tline)
% Increment the row counter
r_cnt=r_cnt+1;
% Parse the line looking for numeric values
while(true)
[str, tline] = strtok(tline);
if(isempty(str))
break
end
% Try to conver the string into a number
tmp_val=str2num(str);
if(~isempty(tmp_val))
% If the token is a number, increment the column counter and
% insert the number in the output matrix
c_cnt=c_cnt+1;
m(r_cnt,c_cnt)=tmp_val;
end
end
% Identify the maximum number not NaN column in the in the output matrix
% so far
max_n_col=max(max_n_col,c_cnt);
% Reset the column counter before nest iteration
c_cnt=0;
% Read next line of the input file
tline = fgets(fp);
end
% After having read all the input file, close it
fclose(fp)
% Clean the output matrix removing the exceeding full NaN rows and columns
m(r_cnt+1:end,:)=[];
m(:,max_n_col+1:end)=[];
m
Input file
% Loc : LAT = -19.6423 LON = -70.817 DEP = 21.5451196625
% Loc : xxx = -1.234 yyy = -70.000 WIDTH = 333.369 DEP = 456.5451196625
% Loc : zzz = 1.23
Output
m =
-19.6423 -70.8170 21.5451 NaN
-1.2340 -70.0000 333.3690 456.5451
1.2300 NaN NaN NaN
Hope this helps.
I am trying to write a function transform(A) which when given a matrix A returns a new matrix. The new matrix should be obtained according to following:
if A has more than one row then interchange the first and second row. After this square the elements in the first row.
So far thats what I have written:
function[Anew] = transform(A)
dimension = size(A);
if dimension(1) > 1 %if there is more than 1 row
A([1 2],:)=A([2 1],:);
end
A(1,:,:) = A(1,:,:).^2 %squares elements in the first row
end
I tested my function by invoking it in matlab.
I noticed that because i dont have a semi colon next to A(1,:,:) = A(1,:,:).^2
I still obtain the desired result but not as output of the function.
I obtain A =
instead of Anew =
If i put a semi colon next to A(1,:,:) = A(1,:,:).^2; then I dont get an output at all.
Could you tell me what is wrong and what should I change in my program to obtain output as Anew?
Thank you
To return a value from a function in Matlab, you must directly assign to it.
In your case, you need to assign to Anew at the end of the operation (you could also technically just use that variable all-together).
function [Output1, Output2] = SomeFunction( ... )
% Do Some Work
% Store Output
Output1 = Result1(:,2) %some output
Output2 = Result2(3:end, :) %some other result
end
function[Anew] = transform(A)
dimension = size(A);
Anew = A;
if dimension(1) > 1 %if there is more than 1 row
Anew ([1 2],:)=Anew([2 1],:);
end
Anew(1,:,:) = Anew(1,:,:).^2; %squares elements in the first row
end
I have a huge sparse matrix a and I want to save it in a .csv. I can not call full(a) because I do not have enough ram memory. So, calling dlmwrite with full(a) argument is not possible. We must note that dlmwrite is not working with sparse formatted matrices.
The .csv format is depicted below. Note that the first row and column with the characters should be included in the .csv file. The semicolon in the (0,0) position of the .csv file is necessary too.
;A;B;C;D;E
A;0;1.5;0;1;0
B;2;0;0;0;0
C;0;0;1;0;0
D;0;2.1;0;1;0
E;0;0;0;0;0
Could you please help me to tackle this problem and finally save the sparse matrix in the desired form?
You can use csvwrite function:
csvwrite('matrix.csv',a)
You could do this iteratively, as follows:
A = sprand(20,30000,.1);
delimiter = ';';
filename = 'filecontaininghugematrix.csv';
dims = size(A);
N = max(dims);
% create names first
idx = 1:26;
alphabet = dec2base(9+idx,36);
n = ceil(log(N)/log(26));
q = 26.^(1:n);
names = cell(sum(q),1);
p = 0;
for ii = 1:n
temp = repmat({idx},ii,1);
names(p+(1:q(ii))) = num2cell(alphabet(fliplr(combvec(temp{:})')),2);
p = p + q(ii);
end
names(N+1:end) = [];
% formats for writing
headStr = repmat(['%s' delimiter],1,dims(2));
headStr = [delimiter headStr(1:end-1) '\n'];
lineStr = repmat(['%f' delimiter],1,dims(2));
lineStr = ['%s' delimiter lineStr(1:end-1) '\n'];
fid = fopen(filename,'w');
% write header
header = names(1:dims(2));
fprintf(fid,headStr,header{:});
% write matrix rows
for ii = 1:dims(1)
row = full(A(ii,:));
fprintf(fid, lineStr, names{ii}, row);
end
fclose(fid);
The names cell array is quite memory demanding for this example. I have no time to fix that now, so think about this part yourself if it is really a problem ;) Hint: just write the header element wise, first A;, then B; and so on. For the rows, you can create a function that maps the index ii to the desired character, in which case the complete first part is not necessary.
I'm trying to write a matlab function that will load a data into a matrix. The problem is the data has one more value each row. So I can't use load unfortunately, so I'm trying to use fgetl.
The data looks like:
143234
454323 354654
543223 343223 325465
etc
What I did is create a matrix of zeros, the dimensions being the height and the longest string of data. To put the data into the matrix I used fgetl to read each row and then used textscan to split the data up at whitespace. Then I used str2num (I think this is where the error is) to convert the string to a number.
First heres my code:
%READTRI Opens the triangle dat file and turns it into a matrix
fid = fopen('triangledata.dat');
%create matrix of zeros for the data to be retrieved
trimat = zeros(15,15);
%Check to see if the file loaded properly
if fid == -1
disp('File load error')
else
%if it does, continue
%read each line of data into a
while feof(fid) == 0
%run through line by line
aline = fgetl(fid);
%split aline into parts by whitespace
splitstr = textscan(aline,'%s','delimiter',' ');
%This determines what row of the matrix the for loop writes to
rowCount = 1;
%run through cell array to get the numbers out and write them to
%the matrix
for i = 1:length(splitstr)
%convert to number
num = str2num(splitstr{i});
%write num to matrix
trimat(rowCount, i) = num;
end
%iterate rowCount
rowCount = rowCount + 1;
end
%close the file
closeresult = fclose(fid);
%check for errors
if closeresult == 0
disp('File close successful')
else
disp('File close not successful')
end
end
end
The error I'm getting is:
Error using str2num (line 33)
Requires string or character array input.
Error in readTri (line 32)
num = str2num(splitstr{i});
What bothers me is that when I try, in the interactive console the same thing that goes on in the loop i.e. import aline, split it into a cell array using textscan, then use num2str to convert it to a integer. Everything works. So either the way I'm using num2str is wrong or the for loop is doing something funky.
I was just hoping for ideas, there is a LOT of data so adding zeros to make load work is not possible.
thanks for reading!
You can use dlmread instead of load or fgetl
It automatically returns a matrix with zeros whenever the line is not as long as the longest.
Just do
matrix = dlmread('triangledata.dat');
Why not using textscan?
fid = fopen('test.txt','r');
C = textscan(fid, '%f%f%f');
fclose(fid);
res = cell2mat(C)
The result is
res =
143234 NaN NaN
454323 354654 NaN
543223 343223 325465
where missing values are NaN.