I have a line graph with ExamCount and FailureRate as the values, with ExamDate on the X axis.
How would I calculate the the current months FailureRate compared to last month? I have two slicers affecting the graph: SchoolName and ExamDate
try with:
PrevFailureRate = calculate( sum(Table[Failure]), FLITER(ALL(Table[ExamDate]), Table[ExamDate] = SELECTEDVALUE(Table[ExamDate]) - 1 ))
Related
How can I in a smart way get the first business day of a month after the weekend?
To get the first business day of the month (given dateInput), we can do:
firstBusdayMonth = fbusdate(year(dateInput),month(dateInput));
As an example, for November, using the above function will return Thursday November 1 as the first business day. However, the first business day of the month after the first weekend is Monday November 5. How can I get this latter date?
Notes:
The weekend does not have to be in the same month.
If the Monday is not a working day, then I would like it to return the next business day
This function will do the trick. Here is the logic:
Create a datetime array for all days in the given month.
Get the day numbers.
Create a logical array, true from the first Monday onwards (so after the first weekend, accounting for the last day of the previous month being a Sunday).
Create another logical array using isbusday to exclude Mondays which aren't working days.
Finding the first day number where these two logical arrays are true, therefore the first business day after the weekend.
Code:
function d = fbusdateAferWE( y, m )
% Inputs: y = year, m = month
% Outputs: day of the month, first business day after weekend
% Create array of days for the given month
dates = datetime( y, m, 1 ):days(1):datetime( y, m, eomday( y, m ) );
% Get the weekday numbers to find first Monday, 1 = Sunday
dayNum = weekday( dates );
% Create the logical array to determine days from first Monday
afterFirstWeekend = ( cumsum(dayNum==2) > 0 ).';
% Get first day which is afterFirstWeekend and a business day.
d = find( afterFirstWeekend & isbusday( dates ), 1 );
end
You could probably speed this up (although it will be pretty rapid already) by not looking at the whole month, but say just 2 weeks. I used eomday to get the last day of the month, which means I don't have to make assumptions about a low number of holiday days in the first week or anything.
Edit: Working with datenum speeds it up by half (C/O JohnAndrews):
function d = fbusdateAferWE( y, m )
% Inputs: y = year, m = month
% Outputs: day of the month, first business day after weekend
% Create array of days for (first 2 weeks of) the given month
dates = datenum(datetime(y,m,1)):datenum(datetime(y,m,eomday(y,m)))-14;
% Get the weekday numbers to find first Monday, 1 = Sunday
dayNum = weekday( dates );
% Create the logical array to determine days from first Monday
afterFirstWeekend = ( cumsum(dayNum==2) > 0 ).';
% Get first day which is afterFirstWeekend and a business day.
d = find( afterFirstWeekend & isbusday( dates ), 1 );
end
I would add something like this after your statement:
[DayNumber, DayName] = weekday(firstBusdayMonth);
if DayNumber > 2
day = 10 - DayNumber;
else
This works because 'weekday' will return a number between 1 (Sunday) and 7 (Saturday).
The fbusdate() function will never return a 1 or 7, so we can ignore those cases.
If weekday(fbusdate()) == 2, the first is on a Monday and the firstBusdayMonth variable doesn't need to be changed.
If weekday(firstBusdayMonth) returns between 2 and 6, we need to skip to the next week, so we subtract the weekday value from 10 to find the next Monday.
It might not be the most elegant solution, but should work.
We can use fbusdate to get the first business day of a month:
Date = fbusdate(Year, Month);
However, how do we get the first business day of a week?
As an example, during the week that I'm posting this, Monday 09/07/2017 was a holiday in the US:
isbusday(736942) % = 0
How do I determine that the first business day for this week would be the next day 736943?
I'm not aware of a builtin function that returns the first working day of a week, but you can obtain it by requesting the next working day after Sunday:
busdate(736941); % 736941 = Sunday 09/03/2017
Your desired fbusdateweek function can be done in one line using just the function weekday to get the first Sunday of the week then busdate to get the next business day after that:
dn = 736942; % Date number for any day in a week
Date = busdate(dn-weekday(dn)+1);
Note: busdate uses the function holidays by default to get all holidays and special nontrading days for the New York Stock Exchange. If necessary, you can define an alternate set of holidays for busdate to use as follows:
holidayArray = ...; % Some set of date numbers, vectors, or datetimes
Date = busdate(dn-weekday(dn)+1, 1, holidayArray);
This way you can define a set of localized holidays.
Solved it. Here is a function that is based on the answer of #m7913d:
function Busday = fbusdateweek(date)
% Return the first business day after Sunday
% 'date' is a datenum input
dperiod = date-6:date;
sundays = weekday(dperiod)==1;
sunday = find(sundays==1,1,'first');
datesunday = dperiod(sunday);
% -->
Busday = busdate(datesunday);
end
In the pic above, the horizontal axis is a day ahead of the actual values. Very new to google charts and cant figure out what the issue could be. I have verified the data being passed to the chart is the 14th, 15th, and 16th.
google.visualization.ComboChart
Found an answer to this. The problem was javascript subtracting a day from the date range.
Here is how I was initially setting the date:
var dt = new Date($(child).text());
dt.setDate(dt.getDate());
addData.push(dt);
Solution
var year = parseInt($(child).text().split("-")[0]);
var month = parseInt($(child).text().split("-")[1])-1;
var day = parseInt($(child).text().split("-")[2]);
var dt = new Date(year, month, day);
addData.push(dt);
I have a dataset for which I have extracted the date at which an event occurred. The date is in the format of MMDDYY although MatLab does not show leading zeros so often it's MDDYY.
Is there a method to find the mean or median (I could use either) date? median works fine when there is an odd number of days but for even numbers I believe it is averaging the two middle ones which doesn't produce sensible values. I've been trying to convert the dates to a MatLab format with regexp and put it back together but I haven't gotten it to work. Thanks
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
You can use datenum to convert dates to a serial date number (1 at 01/01/0000, 2 at 02/01/0000, 367 at 01/01/0001, etc.):
strDate='27112011';
numDate = datenum(strDate,'ddmmyyyy')
Any arithmetic operation can then be performed on these date numbers, like taking a mean or median:
mean(numDates)
median(numDates)
The only problem here, is that you don't have your dates in a string type, but as numbers. Luckily datenum also accepts numeric input, but you'll have to give the day, month and year separated in a vector:
numDate = datenum([year month day])
or as rows in a matrix if you have multiple timestamps.
So for your specified example data:
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
years = mod(dates,100);
dates = (dates-years)./100;
days = mod(dates,100);
months = (dates-days)./100;
years = years + 1900; % set the years to the 20th century
numDates = datenum([years(:) months(:) days(:)]);
fprintf('The mean date is %s\n', datestr(mean(numDates)));
fprintf('The median date is %s\n', datestr(median(numDates)));
In this example I converted the resulting mean and median back to a readable date format using datestr, which takes the serial date number as input.
Try this:
dates=[32381 41081 40581 32381 32981 41081 40981 40581];
d=zeros(1,length(dates));
for i=1:length(dates)
d(i)=datenum(num2str(dates(i)),'ddmmyy');
end
m=mean(d);
m_str=datestr(m,'dd.mm.yy')
I hope this info to be useful, regards
Store the dates as YYMMDD, rather than as MMDDYY. This has the useful side effect that the numeric order of the dates is also the chronological order.
Here is the pseudo-code for a function that you could write.
foreach date:
year = date % 100
date = (date - year) / 100
day = date % 100
date = (date - day) / 100
month = date
newdate = year * 100 * 100 + month * 100 + day
end for
Once you have the dates in YYMMDD format, then find the median (numerically), and this is also the median chronologically.
You see above how to present dates as numbers.
I will add no your issue of finding median of the list. The default matlab median function will average the two middle values when there are an even number of values.
But you can do it yourself! Try this:
dates; % is your array of dates in numeric form
sdates = sort(dates);
mediandate = sdates(round((length(sdates)+1)/2));
I'm aware that there are several Cocoa Touch/iPhone calendar implementations available online, but for certain reasons I'm trying to create my own. I'm running into an issue where the code that I use to lay out the dates (which I represent as instances of UIView placed as subviews into another UIView) is messing up in December.
Currently, what I do is decompose the date into an instance of NSDateComponents, then get the week and weekday properties of the components to figure out the X and Y "positions" of the date view, respectively. I can offset the X position by the week property for the first day of the month I'm laying out.
Brief example: the first day of August 2009 falls on a Saturday, and its date components' week property is 31 (using a Gregorian calendar). Therefore its Y position is 6 and its X position is 0, and the X offset I'll be using is 31. So I can take the second day of August, which is a Sunday, and determine that its X position is 0 and its Y position is week - 31 = 32 - 31 = 1. This way I can lay out a zero-indexed grid of date views for the month of August, and it all goes swimmingly...
...until I try to do the same for December. In December of 2009, apparently the week property wraps to 1 on the 27th (a Sunday), meaning that I wind up trying to place the 27th through the 31st at Y positions -48 or so.
My question is twofold: why does the week property wrap partway into the last month of the year? Is it indexed at the last Sunday of the previous year, rather than the first day of the year? And second, is there a better way to lay out a date grid like this (using other components from an NSDateComponents instance, or anything else I can get from an NSDate and an NSCalendar), or do I just have to add a check for the "last week of year" condition?
The last few days in December start to belong to week 1 of the next year. (see here)
Instead of using the week property to calculate the weekday positions, I'd just start with Y=0 and then increase it after each Saturday (if your week starts on Sundays)
int x = <calculate x based on the weekday of the 1st of the month>
int y = 0
for (days in month) {
<add subview for this day>
x += xOffset
if (currentWeekday == saturday) {
x = 0
y += yOffset
}
}
P.S.: I'd probably look at the current locale to determine the first weekday:
NSLocale *locale = [NSLocale currentLocale];
NSCalendar *calendar = [locale objectForKey:NSLocaleCalendar];
NSUInteger firstWeekday = [calendar firstWeekday];
I probably wouldn't use weeks in my calculation. You need to lay out the days in rows of 7, which of course we know conceptually as weeks. Practically you should be able to get away just knowing the day of the year and doing a modulus.
Say the year starts on Sunday (column 1) and you want know the position of the 100th day. Well 100 / 7 = 14 with a remainder. So it is in the 14th row. Then do a mod 100 % 7 = 2. So it falls on a Monday (in my example).