Is it possible to concatenate multiple variable horizontally to make a single variable in Matlab?
For Example, I want to join:
year = 2001, month = 06, day = 15
to make one variable '20010615' which I could search in a matrix.
I hope I am clear.
Regards,
If you want a string output, use string formatting and sprintf
sprintf('%04d%02d%02d', year, month, day );
If you want a numeric output, simply multiply
day + 100 * month + 10000 * year
Update:
Thanks to #Joshua's comment: if you are indeed working with date/time information you should also look into datestr that allows more speciallized formatting for date and time information.
Related
I'm having some issues creating a function with the following parameters:
Ndata = extperiod(data, year, month,time)
The data is a table with 3 columns, which from left to right are:
year/month/date, time, temperature
My goal is to create a function which can extract a time and a year/month, irrespective of the date and find it's corresponding temperature.
I need to avoid using for loops
I've been advised to use floor and find, where floor(YYYYMMDD/100) = YYYY*100 + MM, which I somehow want to integrate to my function.
I've previously found a way to extract all temperatures from the data for a given day, as follows:
k = find(data(:,1)==19750101);
data(k(1):k(end),3)
I'm trying to incorporate this method, but I think that the hint "floor(YYYYMMDD/100)" throws me a of a little.
I have tried with find(data(:,1)==floor(YYYYMMDD/100)), where I would think that I'd be given all dates with a specific year and month. For example:
find( data(:,1) == floor(19660101/100) )
I thought this would give me all points in the column vector where the value is 196601. But it doesn't.
What could I try differently?
From your explanation, your want to get all temperature for a given month, no matter time and day.
So you want to find dates that are comprised in the range [YYYYMM ; YYYY{MM+1}[ or [YYYYMM ; {YYYY+1}01[ in the case of selecting December.
Recall that you store the complete date in your table. So you need to apply your operator floor to both sides of your query, not only on the query value, because no date is floor(YYYYMMDD/100)!
As a result, try the following:
find( floor(data(:,1)/100) == floor(19660101/100) )
i would like to simulate random timestamp data.
100 records in a day for one year.
How am I am able to do that?
when i set a:2013.01.01D00:00:00.000000000
100?a
the randomize data doesn't stay in a day.
thanks for your input
I am not sure, if this can be done easily. But you may generate 100 random timestamps for every day of 2013 in the next way
daysInYear: 365;
year: 2013.01.01D00:00:00.000000000;
//array of 365 elements, where every element represents corresponding date of year
dates: year + 01D * til daysInYear;
//array of 365 elements, where every element is an array of 100 random timestamps [0 .. 1D)
randomNanos: cut[100; (100 * daysInYear)?1D];
//array of 365 elements, where each element is an array of 100 random dateTimes for given day
result: dates + randomNanos;
//put all the dates in single array
raze result
The short version which does the same is below:
raze (2013.01.01D+01D * til 365) + cut[100; (100*365)?1D]
In order to simulate data for a single day, it's possible to generate random times (as floats less than one) and add them to the day you would like to generate data for. In this case:
D:2016.03.01;
D+100?1f
Will return 100 random times on 2016.03.01. If you want to generate data within a time range you can restrict the size of the float to something less than 1, or greater than a certain minimum value.
If you want to handle leap years... Not sure of a better way at the minute other than adding the max number of days onto the start of the year and asking whether it's the 31st. Adding on 366, it can either be 31st or 1st. If it's the 31st good, otherwise drop off the last date.
/e.g.
q)last 2015.01.01+til 365
2015.12.31
q)last 2016.01.01+til 365
2016.12.30 /we are a day short
q)
/return the dates and the number of days based on whether its a leap year
q)dd:$[31i~`dd$last d:2016.01.01+til 366;(366;d);(365;-1_d)]
q)/returns (366;2016.01.01 2016.01.02...)
q)/the actual logic below is pretty much the same as the other answer
q)raze{[n;dy;dt] dt+n cut(n*dy)?.z.N}[100;].dd
2016.01.01D16:06:53.957527121 2016.01.01D10:55:10.892935198 2016.01.01D15:36:..
The code below gives a decimal day for one specific year.
HolidayArrayDate(2) = datenum(2012,01,16,00,00,00); %MartinLutherKingJrBirthday
I am trying to make the holiday more general for an input "dataYear" instead of specifying it as "2012". Martin Luther King Jr Birthday is the third Monday of ever year. When i provide it an input of any year 2010/2011/2012/2013/2014 through "dataYear", it should automatically choose the third Monday in January for me. How would i dot this?
Thank you!
Starting from the first day of the year, 21 days always suffice to find the third Monday. So: get serial date number for first day of the year (with datenum); get day-of-the-week for that and the following 20 days (datestr(..., 'd')); find the first three Mondays (find(...=='M', 3); and finally pick the third one and convert it into date string (datestr):
dataYear = 2012; %// input
f = datenum(dataYear,1,1); %// 1st day of year, in serial date number format
r = find(datestr(f+(0:20), 'd')=='M', 3); %// find three Mondays from that day on
result = datestr(f+r(3)-1); %// third Monday, in date string format
I have a matrix containing the date in a cell structure. I managed to convert the date (2nd column) using datenum(), but I am not sure how to add on the time (3rd column)
The data looks like this:
'IBM' 20090602 0 108.410000000000
'IBM' 20090602 500 108.560000000000
My code:
date = datenum(num2str(IBM(:,2)),'yyyymmdd')
Let's review your mistakes first:
You feed datenum with the string 'IBM(:, 2)' instead of the actual array. Discard the quotes.
datenum accepts strings, not numerical values.
A possible solution is converting the second column of your data into an array of strings, and feeding it into datenum, like so:
d = datenum(num2str(vertcat(IBM{:, 2})), 'yyyymmdd');
Note that this is, of course, possible only if the format of the date string is fixed in each row.
EDIT:
To add the values in the third column to the result of datenum, simply do the following:
d + vertcat(IBM{:, 3})
Where d is a column vector of date values obtained from datenum (I assume that you want to do basic addition, since you haven't specified the actual meaning of the timje values in the third column).
In one line, the complete answer would look like this:
datenum(num2str(vertcat(IBM{:, 2})), 'yyyymmdd') + vertcat(IBM{:, 3})
You can straight-up add the time values in when you're converting to datenum. Just convert from what I assumed were minutes (if they're in seconds, add in another *60 to the divisor) to days, which is what MATLAB uses for its datenum calculations.
timestamps = cellfun(#(x,y) datenum(num2str(x),'yyyymmdd')+y/(24*60),...
IBM(:,2),...
IBM(:,3),...
'UniformOutput',false)
I have some data that was given to me in excel and the time format is rather confusing. The fist column of the is the DateTime but with incorrect HH:MM and the second column is the correct hour of the day HH:MM:
time = {'01/01/2000 00:00',num2str(2300);
'01/01/2000 00:00',num2str(2400);
'01/01/2000 00:00',num2str(10);
'01/01/2000 00:00',num2str(100)};
However, when the time exceeds midnight, instead of being 00:10 the time is 10, and 01:00 is 100. How could I alter these to the correct format? i.e. from the example above I would like the outcome to be:
time = {'01/01/2000 23:00';
'01/01/2000 24:00';
'01/01/2000 00:10';
'01/01/2000 01:00'};
How could I achieve this?
Using sprintf in MATLAB, you can use the field width specifier:
where
Field width:
Minimum number of characters to print. Can be a number, or an asterisk (*) to refer to an argument in the input list. For example, the input list ('%12d', intmax) is equivalent to ('%*d', 12, intmax).
Thus your times should end up all looking like "XX:XX", with the leading zero added by the sprintf if it is missing and the colon added in.
Thanks to #Junuxx for the exact command: sprintf('%02i:%02i', hours, minutes)
To separate hours and minutes, you would obviously do time % 100 to get the minutes and integer divide by 100 to get the hours.
From there, you simply strcat or concatenate ["a" "b"] your two columns to get your desired result.