I would like to check whether the date I pass in into a function comes after 01/02 or 01/08. How do i do that in Matlab? This comparsion does is independent of the year.
Need some guidance on this.
Btw, how do u calculate the difference between dates irregardless of year?
Use datenum, with a format specifier if you want to be explicit:
D0 = datenum('01/02','mm/dd'); % current year is inferred (irrelevant)
D1 = datenum('01/08'); % 'mm/dd' is inferred
This allows you to test with regular comparison operators:
>> D = datenum('01/03')
>> D > D0
ans =
1
>> D > D1
ans =
0
Related
I am facing an issue with counting number of occurrences by date, suppose I have an excel file where the data is as follows:
1/1/2001 23
1/1/2001 29
1/1/2001 24
3/1/2001 22
3/1/2001 23
My desired output is:
1/1/2001 3
2/1/2001 0
3/1/2001 2
Though 2/1/2001 does't appear in the input, I want that included in the output with 0 counts. This is my current code:
[Value, Time] = xlsread('F:\1km\fire\2001- 02\2001_02.xlsx','Sheet1','A2:D159','',#convertSpreadsheetExcelDates);
tm=datenum(Time);
val=Value(:,4);
data=[tm val];
% a=(datestr(tm));
T1=datetime('9/23/2001');
T2=datetime('6/23/2002');
T = T1:T2;
tm_all=datenum(T);
[~, idx] = ismember(tm_all,data(:,1));
% idx=idx';
out = tm_all(idx);
The ismember function does not seem to work, because the length of tm_all is 274 and the size of data is 158x2
I suggest you to use datetime instead of datenum for converting your date strings into a serial representation, this can make (not only) the whole computation much easier:
tm = datetime({
'1/1/2001';
'1/1/2001';
'1/1/2001';
'3/1/2001';
'3/1/2001'
},'InputFormat','dd/MM/yyyy');
Once you have obtained your datetime vector, the calculation can be achieved as follows:
% Create a sequence of datetimes from the first date to the last date...
T = (min(tm):max(tm)).';
% Build an indexing of every occurrence to the regards of the sequence...
[~,idx] = ismember(tm,T);
% Count the occurrences for every occurrence...
C = accumarray(idx,1);
% Put unique dates and occurrences together into a single variable...
res = table(T,C)
Here is the output:
res =
T C
___________ _
01-Jan-2001 3
02-Jan-2001 0
03-Jan-2001 2
For more information about the functions used within the computation:
accumarray function
ismember function
On a side note, I didn't understand whether your dates are in dd/MM/yyyy or in MM/dd/yyyy format... because with the latter, you cannot have that output using my approach, and you should also implement an algorithm for detecting the current month and then splitting your data over a monthly (and eventually yearly, if your dates span over 2001) criterion instead:
tm = datetime({
'1/1/2001';
'1/1/2001';
'1/1/2001';
'3/1/2001';
'3/1/2001'
},'InputFormat','MM/dd/yyyy');
M = month(tm);
M_seq = (min(M):max(M)).';
[~,idx] = ismember(M,M_seq);
C = accumarray(idx,1);
res = table(datetime(2001,M_seq,1),C)
res =
Var1 C
___________ _
01-Jan-2001 3
01-Feb-2001 0
01-Mar-2001 2
I'll first give the code and then explain step by step.
code:
[Value, Time] = xlsread('stack','A1:D159','',#convertSpreadsheetExcelDates);
tm=datenum(Time);
val=Value(:,4);
data=[tm val];
a=(datestr(tm));
T1=datetime('1/1/2001');
T2=datetime('6/23/2002');
T = T1:T2;
tm_all=datenum(T);
[~, idx] = ismember(tm_all,data(:,1)); % get indices
[occurence,dates]= hist(data(:,1),unique(data(:,1))); % count occurences of dates from file
t = [0;data(:,1)]; % add 0 to dates (for later because MATLAB starts at 1
[~,idx] = ismember(t(idx+1),dates); % get incides
q = [0 occurence]; % add 0 to occurence (for later because MATLAB starts at 1
occ = q(idx+1); % make vector with occurences
out = [tm_all' occ']; % output
idx of ismember is an 1xlength(tm_all) vector that at position i contains the lowest index of where tm_all(i) is found in data(:,1). So take for example A = [1 2 3 4] and B = [1 1 2 4] then for [~,idx] = ismember(A,B) the result will be
idx = [1 3 0 4]
because A(1) = 1 and the first 1 in B is found at posistion 1. If a number in A doesn't occur in B, then the result will be 0.
[occurence,dates]= hist(data(:,1),unique(data(:,1))); gives the number of occurences for the dates.
t = [0;data(:,1)]; adds a zero in the beginning so tlooks like:
0
'date 1'
'date 2'
'date 3'
'date 4'
...
Why this is done, will be explained next.
t(idx+1) is a vector that is 1xlength(tm_all), and is kind of a copy of tm_all except that when a date doesn't occur in the file, the date is zero. How does this work? t(i) gives you the value of t at position i. So t( 1 5 4 2 9) is a vector with the values of t at positions 1, 5, 4, 2 and 9. Remember idx is the vector that contains the incides of the of the dates in data(:,1). Because Matlab indexing starts at 1, idx+1 is needed. The dates in data':,1) then must also be increased. That's done by adding the zero in the beginning.
[~,idx] = ismember(t(idx+1),dates); is the same as before, but idx now contains the indices of dates.
q = [0 occurence]; again adds a zero occ = q(idx+1); is the row of occurences of the dates.
I have a problem with the mod function output in Matlab. I am trying to perform some calculations for ECC double and add algorithm. I am reading data from a file and storing it in a variable and then performing some operations. All works smoothly except that I get 0 in temp1 when I use mod(X2,P). However if I put in values stored in X2(3.0323e+153) and P(1.1579e+77) on command window (mod( 3.0323e+153, 1.1579e+77)), I get the correct values. Can anyone please help me? Below is the part of script which is problematic.
P = hex2dec('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
line = fread(fileID,[1,67],'*char');
while ~feof(fileID)
PX = line(4:67);
X = hex2dec(PX);
X2 = X^2;
temp1= mod(X2 , P)
end
line = fread(fileID,[1,69],'*char');
end
fclose(fileID);
I think the problem lies with how you're initializing P. From the documentation for hex2dec (emphasis mine):
d = hex2dec('hex_value') converts hex_value to its floating-point integer representation. The argument hex_value is a hexadecimal integer stored as text. If the value of hex_value is greater than the hexadecimal equivalent of the value returned by flintmax, then hex2dec might not return an exact conversion.
And the value of flintmax is:
>> flintmax
ans =
9.007199254740992e+15
Quite a bit smaller than your value for P. In fact, if we use num2hex to look at the two ways you initialize P, you can see a clear difference:
>> P = hex2dec('FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
>> num2hex(P)
ans =
4ff0000000000000
>> num2hex(1.1579e+77)
ans =
4fefffda293c30de
As it turns out, the inexact conversion done by hex2dec results in a number that evenly divides into 3.0323e+153, thus giving you a remainder of 0:
>> mod(3.0323e+153, P)
ans =
0
>> mod(3.0323e+153, 1.1579e+77)
ans =
8.795697942083107e+76
I'm trying to convert a character vector (200,000 rows) into Matlab serial numbers.
The format is '01/07/2015 00:00:59'.
This takes an incredibly long time, and online I can only find tips for solving this in Matlab. Any ideas how I can improve this?
You can use the datenum(datevector) type of input for datenum.
It is much faster than the string parsing. I frequently use this trick whenever I have to import long date/time data (which is nearly everyday).
It consists in sending a mx6 (or mx3) matrix, containing values representing [yy mm dd HH MM SS]. The matrix should be of type double.
It means instead of letting Matlab/Octave do the parsing, you read all the numbers in the string with your favourite way (textscan, fscanf, sscanf, ...), then you send numbers to datenum instead of string.
In the example below I generated a long array (86401x19) of date string as sample data:
>> strDate(1:5,:)
ans =
31/07/2015 15:10:13
31/07/2015 15:10:14
31/07/2015 15:10:15
31/07/2015 15:10:16
31/07/2015 15:10:17
To convert that to datenum faster than by the conventional way, I use:
strDate = [strDate repmat(' ',size(strDate,1),1)] ; %// add a whitespace at the end of each line
M = textscan( strDate.' , '%f/%f/%f %f:%f:%f' ) ; %'// read each value independently
M = cell2mat(M) ; %// convert to matrix
M = M(:,[3 2 1 4 5 6]) ; %// reorder columns
dt = datenum(M ) ; %// convert to serial date
This should bring speed up in Matlab but I am pretty sure it should improve things in Octave too. To quantify that at least on Matlab, here's a quick benchmark:
function test_datenum
d0 = now ;
d = (d0:1/3600/24:d0+1).' ; %// 1 day worth of date (one per second)
strDate = datestr(d,'dd/mm/yyyy HH:MM:SS') ; %'// generate the string array
fprintf('Time with automatic date parsing: %f\n' , timeit(#(x) datenum_auto(strDate)) )
fprintf('Time with customized date parsing: %f\n', timeit(#(x) datenum_preparsed(strDate)) )
function dt = datenum_auto(strDate)
dt = datenum(strDate,'dd/mm/yyyy HH:MM:SS') ; %// let Matlab/Octave do the parsing
function dt = datenum_preparsed(strDate)
strDate = [strDate repmat(' ',size(strDate,1),1)] ; %// add a whitespace at the end of each line
M = textscan( strDate.' , '%f/%f/%f %f:%f:%f' ) ; %'// read each value independently
M = cell2mat(M) ; %// convert to matrix
M = M(:,[3 2 1 4 5 6]) ; %// reorder columns
dt = datenum(M ) ; %// convert to serial date
On my machine, it yields:
>> test_datenum
Time with automatic date parsing: 0.614698
Time with customized date parsing: 0.073633
Of course you could also compact the code in a couple of lines:
M = cell2mat(textscan([strDate repmat(' ',size(strDate,1),1)].','%f/%f/%f %f:%f:%f'))) ;
dt = datenum( M(:,[3 2 1 4 5 6]) ) ;
But I tested it and the improvement is so marginal that it is not really worth the loss of readability.
I have strings of the format '15:10:21' for time, and I also know the date, which is in the format 2011-08-05.
What's the best way to obtain matlab time (in days since 1900) out of this data?
Use datenum:
>> num = datenum('2011-08-05 15:10:21')
num =
7.3472e+05
>> datestr(num)
ans =
05-Aug-2011 15:10:21
The "matlab time" is actually days since the 0th of January, in the year 0:
>> datestr(0)
ans =
00-Jan-0000
I need to subtract 21 months from a given date.
My solution as given below only takes me to the first month of the given year :(
[a,b,c]= datevec(date);
b= b-21;
datestr(datenum(a,b,c)) %--> 11-Jan-2011 (WRONG).
I want the answer to be 11-June-2009.
Go via date numbers rather than date vectors and use addtodate:
>> d = datenum(date);
>> e = addtodate(d, -21, 'month');
>> datestr(e)
ans =
11-Jun-2009