Tag the 6 first wording days of the month - powerbi

I am trying to find a way to tag the 6 first wording days (Monday to Friday) of the month.
For example, for November I want:
Date
FlagDate
11/01/2021
True
11/02/2021
True
11/03/2021
True
11/04/2021
True
11/05/2021
True
11/06/2021
False
11/07/2021
False
11/08/2021
True
11/09/2021
False
11/10/2021
False
11/11/2021
False
11/12/2021
False
11/13/2021
False
11/14/2021
False
11/15/2021
False
11/16/2021
False
11/17/2021
False
11/18/2021
False
11/19/2021
False
11/20/2021
False
11/21/2021
False
and so on.

Here is M code that adds a column to your existing table.
It assumes that the column Name in your table is Date
It also assumes you have a List of the relevant holiday dates spanning at least the relevant time frame. I obtained the list from https://publicholidays.fr and buffered it to keep it from continuously downloading
See the comments in the M-Code to understand the algorithm
Note that there is no requirement that the Date column encompasses a full month. But if it starts on, for example, the 15th, there will be nothing in that month marked TRUE since the first6 are not there.
Assumption: Date column spans less than 1 year
If that is not the case, will need a different algorithm to create the first6 list.
M Code
//Before adding the "Flag" column enter this code to create a buffered list of working days in the months in the Date column
workingDays =
let
//generate list of all dates from beginning of first month to the last date listed
dts = List.Transform(
{Number.From(Date.StartOfMonth(#"Previous Step"[Date]{0}))..
Number.From(List.Max(#"Previous Step"[Date]))},each Date.From(_)),
//Using List.Generate, create a list of working days from the preceding list
//working days will be days that are Monday-Friday and NOT found in the list of Holiday dates
wdys = List.Generate(
()=>[wd=if Date.DayOfWeek(dts{0})>= Day.Monday
and Date.DayOfWeek(dts{0})<=Day.Friday
and not List.Contains(#"FR Holidays",dts{0}) then dts{0} else null,
idx = 0],
each [idx] < List.Count(dts),
each [wd=if Date.DayOfWeek(dts{[idx]+1})>= Day.Monday
and Date.DayOfWeek(dts{[idx]+1})<=Day.Friday
and not List.Contains(#"FR Holidays",dts{[idx]+1}) then dts{[idx]+1} else null,
idx = [idx]+1],
each [wd]),
//clean the wdys List by removing the Nulls
cleanList = List.RemoveNulls(wdys),
//create a list of the Months within the workday list
monthsInList= List.Distinct(List.Transform(cleanList, each Date.Month(_))),
//Use List.Accumulate to create lists of the first 6 working days in each month
first6 = List.Accumulate(monthsInList,{},
(state, current)=> state &
List.FirstN(List.Select(cleanList,each Date.Month(_)=current),6))
in List.Buffer(first6),
//Now add a column and set the flag if a Date in the date column is found in the first6 list
flagged = Table.AddColumn(#"Previous Step","FlagDate", each List.Contains(workingDays,[Date]), type logical)
in
flagged
filtered to show only dates marked True
M Code Edited to handle spans of more than one year
Change MonthsInList to include the year, and also Test for that in the List.Accumulate step
//Before adding the "Flag" column enter this code to create a buffered list of working days in the months in the Date column
workingDays =
let
//generate list of all dates from beginning of first month to the last date listed
dts = List.Transform(
{Number.From(Date.StartOfMonth(#"Previous Step"[Date]{0}))..
Number.From(List.Max(#"Previous Step"[Date]))},each Date.From(_)),
//Using List.Generate, create a list of working days from the preceding list
//working days will be days that are Monday-Friday and NOT found in the list of Holiday dates
wdys = List.Generate(
()=>[wd=if Date.DayOfWeek(dts{0})>= Day.Monday
and Date.DayOfWeek(dts{0})<=Day.Friday
and not List.Contains(#"FR Holidays",dts{0}) then dts{0} else null,
idx = 0],
each [idx] < List.Count(dts),
each [wd=if Date.DayOfWeek(dts{[idx]+1})>= Day.Monday
and Date.DayOfWeek(dts{[idx]+1})<=Day.Friday
and not List.Contains(#"FR Holidays",dts{[idx]+1}) then dts{[idx]+1} else null,
idx = [idx]+1],
each [wd]),
//clean the wdys List by removing the Nulls
cleanList = List.RemoveNulls(wdys),
//create a list of the Months within the workday list
monthsInList= List.Distinct(List.Transform(cleanList, each Date.ToText(_,"yyyy-MM"))),
//Use List.Accumulate to create lists of the first 6 working days in each month
first6 = List.Accumulate(monthsInList,{},
(state, current)=> state &
List.FirstN(List.Select(cleanList,each Date.ToText(_,"yyyy-MM")=current),6))
in List.Buffer(first6),
//Now add a column and set the flag if a Date in the date column is found in the first6 list
flagged = Table.AddColumn(#"Previous Step","FlagDate", each List.Contains(workingDays,[Date]), type logical)
in
flagged

You can create a custom column with DAX with the following formula
= CONTAINS(TOPN(6,FILTER('Table',WEEKDAY('Table'[Date],2)<6)),'Table'[Date],'Table'[Date])
You can update TopN(6 to accordingly update the number of first working days

Related

vlookup between two worksheets in VBA

i have tried alot doing vlookup between two workbooks, one is open (book1) and the other
needs to be opened by GetOpenFilename() function let us call it (book2).
(book1) contains sheet1 where i want to do the vlookup
(book2) contains sheet2 where i want to match the id (column 1) and get the names (column2) by vlookup.
here is my code. Notice that the number of rows changes every month so, i need to loop until the last row in sheet1(in book1).
Sub status_first_Step()
Range("C:C").Insert
Set book1 = Sheets("Sheet1")
book2 = Application.GetOpenFilename()
Workbooks.Open book2
Set book2 = ActiveWorkbook
For i = 1 To Cells(Rows.Count, "A").End(xlUp).Row
ws1.Cells(i, "C").Value = Application.VLookup(book1.Cells(i, 1).Value, book2.Sheets("sheet2").Columns("A:Y"), 2, 0)
Next i
End Sub
Thank You.

Circular dependency while calculating column

I have a single table of data named RDSLPDSL. I am trying to calculate two columns based on two measures I am creating from the table.
Count of RDSL Marker for 1 =
CALCULATE(
COUNT('RDSLPDSL'[RDSL Marker]),
'RDSLPDSL'[RDSL Marker] IN { 1 }
)
I am using the above code as a measure to look for values only with 1 in it in the RDSL Marker column.
RDSL % = DIVIDE([Count of RDSL Marker for 1], COUNTROWS(RDSLPDSL))
Then I created a column using the above code to divide the rows with 1 by the total number of rows in the table.
I am doing the same for another column with PDSL. It is as follows:
Count of PDSL Marker for 1 =
CALCULATE(
COUNT('RDSLPDSL'[PDSL Marker]),
'RDSLPDSL'[PDSL Marker] IN { 1 }
)
PDSL % = DIVIDE([Count of PDSL Marker for 1], COUNTROWS(RDSLPDSL))
But when I do this calculation, I am getting an error for circular dependency detected and not getting the final output even though the same code worked for the previous column.
I tried COUNTAX directly instead of using CALCULATE but that brings up the same error too.
I also tried using measures instead of custom column which seems to remove the error but the output is not what I expect and is incorrect.
Any help for the same would be highly appreciated.

Python Time Series

I am working on a real estate cash-flow simulation.
What I want in the end is a time series where everyday I report if the property is vacant, leased and if I collected rent.
In my present code, I create first a profit array with values of "Leased", "Vacant" or "Today you collected rent of $1000", so I used this to create my time series:
rng=pd.date_range('6/1/2016', periods=len(profit), freq='D')
ts=pd.Series(profit, index=rng)
To simplify, I assumed I collected rent every 30 days. Now I want to be more specific and collect it every 5th day of the month (for example) and be flexible on the day the next tenant will move in.
Do you know commands or a good source where I can learn how to iterate from month to month?
Any help would be appreciated
You can build a sequence of dates using date_range and .shift() (freq='M' is for month-end frequencies) with pd.datetools.day like so:
date_sequence = pd.date_range(start, end, freq='M').shift(num_of_days, freq=pd.datetools.day)
and then use this sequence to select dates from the DateTimeIndex using
df.loc[date_sequence, 'column_name'] = value
Alternatively, you can use pd.DateOffset() like so:
ts = pd.date_range(start=date(2015, 6, 1), end=date(2015, 12, 1), freq='MS')
DatetimeIndex(['2015-06-01', '2015-07-01', '2015-08-01', '2015-09-01',
'2015-10-01', '2015-11-01', '2015-12-01'],
dtype='datetime64[ns]', freq='MS')
Now add 5 days:
ts + pd.DateOffset(days=5)
to get:
DatetimeIndex(['2015-06-06', '2015-07-06', '2015-08-06', '2015-09-06',
'2015-10-06', '2015-11-06', '2015-12-06'],
dtype='datetime64[ns]', freq=None)

Time Series manipulation

So I have a dataframe that I dump a time series into. The index is the date. I need to do calculations based on date.
For eg. I have {
XRT_Close
Date
2010-01-04 35.94
2010-01-05 36.17
2010-01-06 36.50
...
2015-02-07 36.60
2015-02-08 36.52 }
How would I go about doing say... Percentage change of beginning to end of the month? How would I construct a loop to cycle through the months?
Any help will be met with huge appreciation. Thank you.
First create year and month columns:
df['year'] = [x.year for x in df.index]
df['month'] = [x.month for x in df.index]
Group by them:
grouped = df.groupby(['year','month'])
Define the function you want to run on the groups:
def PChange(df):
begin = df['column_name'].iloc[0]
end = df['column_name'].iloc[-1]
return (end-begin)/(end+begin)*100
Apply the function to the groups:
grouped.apply(PChange)
Let me know if it works.

Getting upcoming birthdays using 'date of birth' DateField

I'm trying to get the birthdays in the upcoming 20 days, given the below Person model:
class Person(models.Model):
dob = models.DateField() # date of birth
There are similar questions on SO already (here and here), but these do not cover my use case, as I'm storing a date of birth instead of the next birthday or a timefield.
I've tried to do some things like the following:
from datetime import timedelta, date
today = date.today()
next_20_days = today+timedelta(days=20)
Person.objects.filter(dob__month=today.month, dob__day__range=[today.day, next_20_days.day])
... but I get FieldError: Unsupported lookup 'day' for DateField or join on the field not permitted.
When I do e.g. Person.objects.filter(dob__month=today.month, dob__day=next_20_days.day), I do get the results for exactly 20 days from now. So I potentially could go over each of the 20 days in a loop, but that seems rather ineffective.
Any idea on how to do this the proper way?
FYI, I ended up doing the following which works for me and which does not require raw SQL.
Any improvements would be welcomed :-)
# Get the upcoming birthdays in a list (which is ordered) for the amount of days specified
def get_upcoming_birthdays(person_list, days):
person_list= person_list.distinct() # ensure persons are only in the list once
today = date.today()
doblist = []
doblist.extend(list(person_list.filter(dob__month=today.month, dob__day=today.day)))
next_day = today + timedelta(days=1)
for day in range(0, days):
doblist.extend(list(person_list.filter(dob__month=next_day.month, dob__day=next_day.day, dod__isnull=True)))
next_day = next_day + timedelta(days=1)
return doblist
Caveat: I believe calendars and time is hard. As a result, I feel obligated to warn you that I haven't rigorously tested my proposal. But of course, I think it should work. :)
Unfortunately, I think you should abandon date objects as the additional complication of year data precludes easy selects. Rather, I propose storing the birthday as a MMDD string (comparison of strings works, as long as you format them consistently). You can then compute your next_20_days and convert that to a similar MMDD string, as well as today, then use them as values to compare against.
I have three edge cases you should definitely make sure work:
Normal month rollover. (e.g., June to July)
Leap days -- don't forget to check presence as well as absence of Feb 29.
Year boundary -- you'll need to either do two queries and union the results, or do an OR query using Q objects.
Edit: See also:
How to store birthdays without a year part?
SQL Select Upcoming Birthdays
mySQL SELECT upcoming birthdays
and so on. I just did a Google search for "stack overflow birthday select".
I have been struggling with the same issue for the past days. I think I assembled a pretty solid solution that should allow you easily to derive all the birthdays to come up for the next X days. This query runs against the database-table geburtstage (birthdays) with the following 4 fields: ID (set as primary key) vorname (firstname), nachname (lastname) and geburtstag (birthday). Just create the table, fill in some records and run the query below:
select * FROM (
select curdate() AS today, DAY(CURDATE()) AS d_T, MONTH(CURDATE()) AS m_T, DAY(geburtstag) AS d_G, MONTH(geburtstag) AS m_G, subdate(CURDATE(),-20) AS date_20, DAY(subdate(CURDATE(),-20)) AS d_20, MONTH(subdate(CURDATE(),-20)) AS m_20, vorname, nachname, geburtstag, (YEAR(CURRENT_TIMESTAMP) - YEAR(geburtstag) +1 - CASE WHEN MONTH(CURRENT_TIMESTAMP) < MONTH(geburtstag) THEN 1 WHEN MONTH(CURRENT_TIMESTAMP) > MONTH(geburtstag) THEN 0 WHEN DAY(CURRENT_TIMESTAMP) <= DAY(geburtstag) THEN 1 ELSE 0 END) AS age, datediff(DATE_FORMAT(geburtstag,concat('%',YEAR(CURDATE()),'-%m-%d')),NOW()) AS no_of_days FROM geburtstage
union
select curdate() AS today, DAY(CURDATE()) AS d_T, MONTH(CURDATE()) AS m_T, DAY(geburtstag) AS d_G, MONTH(geburtstag) AS m_G, subdate(CURDATE(),-20) AS date_20, DAY(subdate(CURDATE(),-20)) AS d_20, MONTH(subdate(CURDATE(),-20)) AS m_20, vorname, nachname, geburtstag, (YEAR(CURRENT_TIMESTAMP) - YEAR(geburtstag) +1 - CASE WHEN MONTH(CURRENT_TIMESTAMP) < MONTH(geburtstag) THEN 1 WHEN MONTH(CURRENT_TIMESTAMP) > MONTH(geburtstag) THEN 0 WHEN DAY(CURRENT_TIMESTAMP) <= DAY(geburtstag) THEN 1 ELSE 0 END) AS age, datediff(DATE_FORMAT(geburtstag,concat('%',(YEAR(CURDATE())+1),'-%m-%d')),NOW()) AS no_of_days FROM geburtstage) AS upcomingbirthday
WHERE no_of_days >=0 AND no_of_days <= 20 GROUP BY ID
ORDER BY (m_G, d_G) < (m_T, d_T), m_G, d_G, geburtstag desc, age