My data (cell) in Matlab looks like this:
00.00.00.515
00.00.00.671
00.00.00.828
00.00.00.984
00.00.01.140
etc.
This is the time stamp: HH:MM:SS:TTT, the T stands for thousandth (=milliseconds). The milliseconds are important because the step size is small. How to convert this data (cell) to data Matlab can handle (double)?
So the data will be as follow:
0.515
0.671
0.828
0.984
1.140
etc.
The minutes and hours should be converted to seconds so it is easy to calculate the total time of the data or the average stepsize. So:
01.30.00.000
will be:
5400.000
seconds
Thanks!
Assuming your cell array contains strings:
ts = {'00.00.00.515'
'00.00.00.671'
'00.00.00.828'
'00.00.00.984'
'00.00.01.140'};
it can be done as follows:
>> cell2mat(cellfun(#(c) sscanf(c,'%d.%d.%f').', ts, 'uniformout', 0)) * [3600 60 1].'
ans =
0.5150
0.6710
0.8280
0.9840
1.1400
This uses cellfun to convert each cell into a row vector of numbers with sscanf,; then concatenates all those vectos into a matrix with cell2mat; and fianlly applies matrix multiplication to compute time.
The code also works if the number of digits is not fixed. For example:
>> ts = {'0.1.00.51'};
>> cell2mat(cellfun(#(c) sscanf(c,'%d.%d.%f').', ts, 'uniformout', 0)) * [3600 60 1].'
ans =
60.5100
Related
I have a CSV file contains data of Hurricane location coordinates.
I'm new to Matlab so I'm not sure how to treat correctly date and hour cells, especially when they are displayed unconventionally.
I need to apply linear interpolation so I can get the date for every 30 minutes.
Let's assume you read the data in as numerical values
Now you have some matrix like so:
data = [20130928 0 21.1 50.0
20130928 600 22.2 50.3
20130928 1200 23.3 50.6
20130928 1800 24.2 50.6];
To convert the first two columns to datetime values, we could do this:
% Concatenate first two columns, including making all times 4 digits by 0 padding
fulltime = [num2str(data(:,1)), num2str(data(:,2), '%.4u')]
% Use datetime to convert (cell) times to dates with given format
dates = datetime(cellstr(fulltime),'inputformat', 'yyyyMMddHHmm');
>> dates = 28-Sep-2013 00:00:00
28-Sep-2013 06:00:00
28-Sep-2013 12:00:00
28-Sep-2013 18:00:00
Now we can easily interpolate. First create an array of times we want to use:
% Data value every 30 mins
interpdates = dates(1):hours(0.5):dates(end)
Then use interp1
interpolateddata = interp1(dates, data(:,3:4), interpdates);
>> interpolateddata = 21.1000 50.0000
21.1917 50.0250
21.2833 50.0500
21.3750 50.0750
...
24.1250 50.6000
24.2000 50.6000
Consider the following example
xDATA = data_timestamp;
[~,~,Days,Hour,Min,~] = datevec(xDATA(2:end) - xDATA(1:end - 1));
BadSamplingTime = find((Days)> 0 | (Hour)> 0 |(Min)> 5 );
In which xData contains a vector of time stamps and I am trying to find the samples with sampling time greater than 5 mins in between , the algorithm works fine but it creates 3 extra vectors for the data as big as my timestamp vector(the size to time stamp vector is pretty huge) whereas if I do this
DurationTime = xDATA(2:end) - xDATA(1:end - 1);
Instead of the second line it will just create one vector of same length of 'duration' data type which will be much easier to handle because but the problem I cant seem to access each index of the duration data type
for example
DurationTime(5,1)
ans =
26:00:01
I need to access this 26 hours part , does anyone have any idea how to do that ? or a better suggestion
You can create a duration-object and then use it to compare it with the duration vector DurationTime. The result of a>b is a logical vector that can be directly used to index the elements of DurationTime and thus giving you all the values where the duration is greater than 5 minutes.
Sidenote: You can calculate the difference/duration directly with diff.
Code:
% create example data
xDATA = (([0:4,4+26*60,4+26*60+1:4+26*60+5])/24/60+datetime('now')).';
% calculate the durations
DurationTime = xDATA(2:end) - xDATA(1:end-1); % as in the question
%DurationTime = diff(xDATA); % alternative
% get index and values of all durations greater than 5 minutes
ind = find(DurationTime>duration(0,5,0))
DurationTime(ind)
% get values of all durations greater than 5 minutes (direct solution, if no index needed)
DurationTime(DurationTime>duration(0,5,0));
Result:
ind =
5
ans =
26:00:00
My matrix has a coloumn with times in it - times are in milliseconds (milliseconds since midnight - but dont worry about that).
I need to identify the row where the time is 5 seconds less than the last time in the matrix
this is because i am going to loop through the matrix and look at data 5 seconds ahead so I need to know where to end my
for i = 1:rows in matrix minus wherever we hit the last 5 seconds so if looking 5 seconds forward we dont exceed the matrix dimensions.
So lets pretend the time is in coloumn 2 of the matrix
and we have
[rows,coloums] = size(matrix)
the last time stamp in the matrix is (rows,2) and returns time in milliseconds since midnight as for example 53997401 so 5 seconds before or my marker is therefor (53997401-5000)
therefor I am looking to find the last time in coloumn2 which is before the above number or
search look down matrix(:,2) and return the row where (xxx,2) is less than (matrix(rows,2)-5000)
even if it returns a new vector of all rows where coloum2 is less than (matrix(rows,2)-5000) then we can just get the size of that vecor to see what the last row is which meets our criteria
in plain english look down here and return the row where ans < for example 53997364 ie the return would be 4
53984704
53991775
53992283
53992283
53997367
53997367
53997367
53997367
53997401
53997401
For your sample vector (let's call it t):
find(t < t(end) - 5000, 1, 'last')
ans = 4
For the full matrix, it's almost the same thing:
find(matrix(:,2) < matrix(end,2) - 5000, 1, 'last')
I want to do something like
scatter(timesRefined, upProb)
where timesRefined is a cell array in which each entry is a string corresponding to a time moment, such as 8:32:21.122 and upProb is simply a vector of numbers with same length as cell array. What is the most convenient way to do this?
You can convert your timesRefined cell to a numeric representation of date with datenum
>> timesRefined = {'8:32:21.122','9:30:54.123'};
>> datenum(timesRefined)
ans =
734869.355800023
734869.396459757
The resulting number expresses a date as days from the epoch. Since you are not concerned with days, just time, and provided your observations are contained within one day, you can simply take the fractional part of the datenum output:
>> datestr(mod(datenum(timesRefined),1))
ans =
8:32 AM
9:30 AM
and do scater(mod(datenum(timesRefined),1),upProb)
EDIT:
As pointed out by Pursuit, you can use the result of datenum directly as your x values and use datetick('x','HH:MM:SS.FFF')
strsplit from the Matlab file exchange should help. If all values are numeric, you'll get a matrix back.
timestr = '8:32:21.122';
timenum = strsplit(timestr,':');
convmat = [60*60; 60; 1];
time_in_seconds = sum(timenum .* convmat);
I have a matrix ('data') which is composed of day of year in the first column and temperature data in the second column and also a vector ('dDates') of values which also represent day of year. e.g.
clear all
n = 366;
day = linspace(1+1/24,n,(n-1)*24)';
temp = rand(8760,1);
data = [day,temp];
dDates = [12, 32, 45, 67];
I'm trying to alter 'data' so that it only contains data which is measured for the 120 rows following the day number specified in 'dDates' although being the same size as the original 'data' i.e. the other rows filled with nans.
Each measurement in 'data' refers to one hour so 120 refers to 5 days worth of data.
So far I have used:
[r,c,v] = find(data(:,1)>dDates(1),1,'first');
inside a loop to find the row number of each element of 'dDates' in 'dates' but am finding it difficult to bring everything together to produce the outcome that I need. How should I go about doing this?
There's a lot going on here so I made several changes. Generating data can be done avoiding the LINSPACE command. Also, the temperature data is initialized to NaN:
>> n = 366;
>> data = [(1:1/24:(n-1/24))' ones(8760, 1)*NaN];
You can avoid using a loop to find the start indices of each date of interest by calculating the start indices since the date column in data is evenly spaced in time:
>> dDates = [12 32 45 67];
>> startIndex = (dDates - 1) * 24 + 1;
Verify that this worked:
>> data(startIndex)
ans =
12 32 45 67
Generate the random temperature data for the dates of interest:
>> temp = rand(120*length(dDates), 1);
Determine the indices into data that correspond to the start dates of interest and the following 120 records:
>> targetIndex = repmat((0:119)', 1, length(dDates)) + repmat(startIndex, 120, 1);
Slot the random data into the target locations:
>> data(targetIndex, 2) = temp;
Verify that this worked: