This should be straight-forward in MATLAB I just don't know how and am stuck. I have data that looks like this below that is in the form: mm/dd/yyyy hh:mm windspeed - this is hourly data spanning years from 1991 up to the present (2013) of cell arrays and numeric array:
8/22/1993 23:00 2.381453514
8/23/1993 0:00 3.39369154
8/23/1993 1:00 5.398661613
8/23/1993 2:00 7.231492996
8/23/1993 3:00 9.187699318
8/23/1993 4:00 9.802619934
8/23/1993 5:00 8.85418129
8/23/1993 6:00 9.889941216
8/23/1993 7:00 10.4628706
8/23/1993 8:00 10.8967123
8/23/1993 9:00 10.12729263
8/23/1993 10:00 9.106620789
8/23/1993 11:00 7.600066185
8/23/1993 12:00 6.597990036
8/23/1993 13:00 6.764455795
8/23/1993 14:00 7.360760689
8/23/1993 15:00 5.828835011
I am trying to extract the third column only (windspeed). I need to be able to change the date range to extract a month at a time for example ALL the rows containing the month "08" for August of the year 1993 and then for future use all the rows containing "09" for September and the year 2013. I'm not sure if it's better to use datenum or the find function and then how to code this for either case.
I am using xlsread to read the .csv file with a portion of the data shown above.
I don't know how you import your data now, and what your variables in the workspace are, but here's a way to do it:
Find the xxx.csv-file in the Current Folder window in Matlab. Double click it to import it. In the window that appears, you can select Delimiter: Space. Play around with the settings, to find the "best fit"
Now, you have your variable in the Matlab workspace.
hhv = datevec(hh);
% You are interested in column 4, HOUR:
% hhv is a matrix with [2013, 1, 1, HOUR, 0, 0]
Now, if you want all windspeeds between 0:00 and 06:00 08/23/1993:
winds = ws(dt == datenum(1993,8,23) & hhv(:,4) >= 0 & hhv(:,4) < 6)
winds =
3.3937
5.3987
7.2315
9.1877
9.8026
8.8542
A generic way to read the whole file could be:
fid = open('data.csv');
% %d = integer, %f = float
data = textscan(fid, '%d/%d/%d %d:%d %f');
fclose(fid);
% all months in data
disp(data{1});
% all wind speeds in data
disp(data{end});
You can restrict the returned data by modifying the matching pattern in textscan:
% only August
mask = data{1} == 8;
speeds = data{end}(mask);
% June of 1997
mask = (data{1} == 6) & (data{3} == 1997);
speeds = data{end}(mask);
See more here: http://www.mathworks.com/help/matlab/ref/textscan.html#btg0kes
Related
I was working on dates in Matlab and Octave, and the "serial date number" format is documented as
A single number equal to the number of days since January 0, 0000 in the proleptic ISO calendar (specifying use of the Gregorian calendar).
In Octave, they document
Return the date/time input as a serial day number, with Jan 1, 0000 defined as day 1.
The gregorian calender does not use a year zero. But Matlab and Octave refer to the year zero. Does this mean that they refer to year -1 BC, as in the astronomical year numbering?
Days before "October 15, 1582" are "wrong by as much as eleven days", according to the octave manual, which is considerably smaller than a complete year. So I'm trying to sort out this ambiguity.
Firstly, note that the MATLAB and Octave definitions are equivalent
[MATLAB] N = "number of days since Jan 0, 0000" ⇔ [OCTAVE] "Jan 1, 0000 is day 1"
Since N = 1 on day 1.
The Wikipedia page on "Year Zero" (which you linked to) offers this:
[...] the year 1 BC is followed by AD 1. However, there is a year zero in astronomical year numbering (where it coincides with the Julian year 1 BC) and in ISO 8601:2004 (where it coincides with the Gregorian year 1 BC), as well as in all Buddhist and Hindu calendars.
MATLAB and Octave appear to have followed the ISO standard, as stated in the datetime docs:
datetime arrays represent points in time using the proleptic ISO calendar
So the year zero, and hence the datenum value of 1 days, coincides with the first day of 1BC.
Per the definitions at the top of this answer
"day 1"
= 1/Jan/0000
= datenum(1)
= datetime( 1, 'ConvertFrom', 'datenum' )
= datetime( 0, 0, 1 )
We can test using datenum (number of days) and datetime (datetime type object)
datenum( 0, 0, 1 ) % = 1, as defined by the docs
datetime( 1, 'ConvertFrom', 'datenum' )
% = 1/Jan/0000 00:00:00
datetime( 1 + 366, 'ConvertFrom', 'datenum' )
% = 1/Jan/0001 00:00:00
% First day of year 1 after 366 days (leap year 0000 + 1 for Jan 1 )
I'm using D3.js (v3) to plot a time-series graph and I'm trying to figure out the amount of ticks I need for a given month (ie, days). From what I can make of the documentation, d3.time-month should return something from 28 to 31 days, which is what I want, but for some reason I'm obviously missing, I can't seem to get the number I need.
Can anyone help?
This is what I've got so far:
console.log(date); // Fri Jul 01 2016 00:00:00 GMT+0100 (WEST)
monthDays = d3.time.month(date);
console.log(currentMonth+" has "+monthDays+" days."); // July has Fri Jul 01 2016 00:00:00 GMT+0100 (WEST) days.
You're misreading the documentation on intervals : the number of days in the intervals used by d3.time.month have a length between 28 and 31 but the functions are defined as
interval(date)
Alias for interval.floor(date). [...]
and
interval.floor(date)
Rounds down the specified date, returning the latest time interval
before or equal to date. [...]
Basically, d3.time.month(date) will return the first day of the month at midnight, not the number of days in that month.
How to get the number of days then? As far as I can tell, D3 does not expose a way to get the length of the month for a given date. You could of course get the range of days for a given month and extract its length:
var date = new Date(2016, 01, 02); // 2016-02-02
console.log(
d3.time.days(d3.time.month(date), d3.time.month.ceil(date)).length
)
or probably more efficiently use plain JS like in this answer https://stackoverflow.com/a/1185804/1071630 :
var date = new Date(2016, 01, 02); // 2016-02-02
console.log(
new Date(date.getFullYear(), date.getMonth()+1, 0).getDate()
)
var date = new Date(2016, 01, 02);
console.log(
d3.time.days(d3.time.month(date), d3.time.month.ceil(date)).length
)
console.log(
new Date(date.getFullYear(), date.getMonth()+1, 0).getDate()
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
I have a matrix with a timestamp and several column variables.
The matrix spans a month of half hourly variables. Here is a sample of four columns of the matrix
11/11/2015 20:15 31.26410236 35.70104634 35.93171056
11/11/2015 20:45 32.10746291 35.48806277 35.9647747
.
.
.
12/11/2015 20:15 32.10746291 35.48806277 35.9647747
12/11/2015 20:45 32.10746291 35.48806277 35.9647747
.
.
.
13/11/2015 20:15 32.68310429 35.58753807 37.26447422
13/11/2015 20:45 33.05141516 34.8432801 36.48033884
.
.
.
14/11/2015 20:15 32.08328579 34.66482668 34.65446868
14/11/2015 20:45 32.19994433 34.40562145 34.34035989
What is the easiest way to find the average of identical times in terms of hours and minutes?
E.g. mean of each variable at time 20:45 for all days of the month.
I know I could achieve this by converting the timestamp to a datenum, taking the fractional part of datenum and sorting the data by the fractional part of datenum. After that I could block average the rows with similar fractional datenums. Is there a more efficient and more elegant way?
With matlab you can work directly with date and times without converting it to timestamp in miliseconds or seconds:
http://es.mathworks.com/help/matlab/date-and-time-operations-1.html
Or an easy way is to convert dates to a date vector like this:
DateVector = datevec(DateString,formatIn)
then compare the columns you want:
[Y,M,D,H,MN,S] = datevec(___)
>> A = datevec('13/11/2015 20:45','dd/mm/yyyy HH:MM')
A =
2015 11 13 20 45 0
>> B = datevec('14/11/2015 20:45','dd/mm/yyyy HH:MM')
B =
2015 11 14 20 45 0
with this is easy to compare dates:
>> A - B
ans =
0 0 -1 0 0 0
exactly one day difference
This is what I ened up doing to solve this problem:
timestamp=linspace(datenum('2015-11-01 00:00', 'yyyy-mm-dd HH:MM'),datenum('2015-12-01 00:00', 'yyyy-mm-dd HH:MM'),1440); % 30 days
timestamp=timestamp';
time_of_day=datetime(datevec(timestamp(1:48)),'Format','HH:mm');
numdays=30;
data=rand(length(timestamp),2);
means=NaN(48,3);
for tt=1:48
means(tt,:)=[datenum(time_of_day(tt)) nanmean(data(tt:48:48*numdays,:),1)];
end
figure;
plot(time_of_day,means(:,2:3));
xlim([timestamp(1) timestamp(48)]);
As today is Wednesday with date June 8, 2016. how can i write a code to get the day of given dates:
like what day is Nov 29
I'm trying to create a struct with
date
day
month
with month and date as input
Use the builtin weekday() function:
>> [num, name] = weekday('08-Jun-2016')
num =
4
name =
Wed
>> [num, name] = weekday('29-Nov-2016')
num =
3
name =
Tue
In addition to the weekday function, you can use the DDD or DDDD formats in the datestr function, like this:
datestr('08-Jun-2016','DDD') %Returns the string 'Wed'
datestr('08-Jun-2016','DDDD') %Returns the string 'Wednesday'
Or, to use a more practical format
datestr('08-Jun-2016','DDDD, mmmm DD, yyyy')
% Returns the string: 'Wednesday, June 08, 2016'
I have data from a sensor, data were recording for five days non stop. How to select specific rows, related with the certain time, e.g. 11-09-2013 11:20:00 - 11:21:49 PM ? Then, how to divide the obtained data into equal segments 2.56 seconds each?
My data looks like this:
0.135478690266609
0.0537606552243232
-0.0262537784874439
0.157014295458793
0.149360358715057
0.104898564517498
0.0393946692347526
...
and I can read time by using datestr(data(1), 'dd-mm-yyyy HH:MM:SS AM')
If I understand correctly, data is a vector of timestamps in days.
To find the first row that comes after 11-09-2013 11:20:00 PM, you can do:
target = datenum('11-09-2013 11:20:00 PM', 'dd-mm-yyyy HH:MM:SS AM') / 86400;
row = find(data >= target, 1, 'first');
To find all rows between 11-09-2013 11:20:00 PM and 11-09-2013 11:21:49 PM:
start = datenum('11-09-2013 11:20:00 PM', 'dd-mm-yyyy HH:MM:SS AM') / 86400;
stop = datenum('11-09-2013 11:21:49 PM', 'dd-mm-yyyy HH:MM:SS AM') / 86400;
rows = find(data >= start & data <= stop);
To get a segment of 2.56 seconds after the date start, set stop to start + 2.56 / 86400 and use the same trick as above.