def main(): '''Main function call.''' # Initialize File Locator FL = FileLocator() # Gather and read data using latest files, then concatenate together grads = pd.read_excel(dpu.get_latest(FL.students_downloaded, 'NSG_Graduate_Students'), converters={ 'Emplid': str, 'Admit Term': str, 'Maj Adv Emplid': str, 'Run Term': str }) majors = pd.read_excel(dpu.get_latest(FL.students_downloaded, 'NSG_Majors'), converters={ 'Emplid': str, 'Admit Term': str, 'Maj Adv Emplid': str, 'Run Term': str }) df = pd.concat([grads, majors]) # Gather IDs of students in RFU student group rfns = pd.read_excel(dpu.get_latest(FL.students_downloaded, 'RFNS_STDNTGRP'), skiprows=0, header=1, converters={'ID': str}) rfu_ids = rfns['ID'].unique().tolist() # Pandas apply function to determine campus df['Campus'] = df.apply(determine_campus, axis=1, args=(rfu_ids, )) # Archive old student list dpu.archive_old_reports(FL.students, 'Student List', 'Historical Student Lists') # Column names and order column_names = [ 'Emplid', 'Student Name', 'Campus', 'Admit Term', 'Admit Term Desc', 'Acad Level Desc', 'Maj Desc', 'Maj Subplan Desc', 'Maj Adv Name', 'Latest Term Enrl', 'Term Enrl Desc', 'Enrl Hrs', 'Qty Crses', 'Dpu Hrs', 'Transfer Hrs', 'Total Credhrs', 'Term GPA', 'Cum GPA', 'Prefix', 'First Name', 'Middle Name', 'Last Name', 'Suffix', 'Gender', 'Ethnic Group Desc', 'Orig Cntry Des', 'Email', 'Address1', 'Address2', 'City', 'State', 'Postal', 'Best Phone', 'Main Phone', 'Cell Phone', 'Run Term' ] # Gather date date_of_report = datetime.strptime( dpu.get_latest(FL.students_downloaded, 'NSG_Graduate_Students').rstrip('.xlsx')[-10:], '%Y-%m-%d') # Output file output_report(df, column_names, 'Student List', date_of_report, FL.students)
def get_historical_student_data(hist_path, students): # Get a good handful of most recent files stud_files = dpu.get_latest(hist_path, 'Student List', num_files=16) # Iterate through files and concatenate all together for i, file in enumerate(stud_files): if i == 0: historical_students = pd.read_excel(file, header=0, converters={ 'Emplid': str, 'Admit Term': str, 'Latest Term Enrl': str, 'Run Term': str, }) else: historical_students = pd.concat([ historical_students, pd.read_excel(file, header=0, converters={ 'Emplid': str, 'Admit Term': str, 'Latest Term Enrl': str, 'Run Term': str, }) ], ignore_index=True) # Keep only necessary data historical_students = historical_students[[ 'Emplid', 'Last Name', 'First Name', 'Email' ]] # Drop all true duplicates historical_students.drop_duplicates(inplace=True) # Merge with students historical_students = historical_students.merge(students, on='Emplid', how='left', indicator=True, suffixes=['', 'y']) # Remove any exact matches to current students (this does not help us) historical_students = historical_students[historical_students['_merge'] == 'left_only'] # Keep only necessary columns historical_students = historical_students.iloc[:, 0:4] # Reset index historical_students.reset_index(drop=True, inplace=True) return historical_students
def main(prev_date): '''Main function call.''' # Call to FileLocator class FL = FileLocator() # Check if a prev_date was supplied if prev_date: # Test for proper date formatting try: datetime.strptime(prev_date, '%Y-%m-%d') except ValueError: print( 'Date provided was not in a valid format. Please retry using %Y-%m-d format (e.g. 2018-01-24).' ) # Gather absolute paths to previous nc_prev = os.path.abspath( os.path.join(os.sep, FL.health_req_report, 'Downloaded Reports', 'Noncompliant ' + prev_date + '.csv')) cc_prev = os.path.abspath( os.path.join(os.sep, FL.health_req_report, 'Downloaded Reports', 'Compliant ' + prev_date + '.csv')) # Make sure both files exist if os.path.exists(nc_prev) and os.path.exists(cc_prev): num_files = 1 else: raise ValueError( 'Date provided is in a valid format, but compliance files do not exist using that date.' ) else: num_files = 2 print() # Get the latest reports noncompliant_files = dpu.get_latest(FL.health_req_cb_downloads, 'Noncompliant', num_files=num_files) compliant_files = dpu.get_latest(FL.health_req_cb_downloads, 'Compliant', num_files=num_files) if prev_date: # Add previous files noncompliant_files = [noncompliant_files, nc_prev] compliant_files = [compliant_files, cc_prev] if noncompliant_files[0] == noncompliant_files[1] or compliant_files[ 0] == compliant_files[1]: raise 'Previous date provided is same as date of most recent compliance files. Download more recent reports and try again.' else: prev_date = noncompliant_files[1].rstrip('.csv')[-10:] # Get the two most recent reports noncompliant_curr = read_cb(noncompliant_files[0]) noncompliant_prev = read_cb(noncompliant_files[1]) compliant_curr = read_cb(compliant_files[0]) compliant_prev = read_cb(compliant_files[1]) # Get change logs noncompliant_changelog = pd.merge( noncompliant_curr, noncompliant_prev, on=noncompliant_curr.columns.tolist(), how='outer', indicator=True).query("_merge != 'both'").drop('_merge', 1) compliant_changelog = pd.merge( compliant_curr, compliant_prev, on=compliant_curr.columns.tolist(), how='outer', indicator=True).query("_merge != 'both'").drop('_merge', 1) # Get next action date file nad_file = dpu.get_latest(FL.health_req_cb_downloads, 'Next_Action_Date', num_files=1) to_datetime = lambda d: datetime.strptime(d, '%m/%d/%Y') to_string = lambda d: datetime.strftime(d, '%m/%d/%Y') next_action_date = pd.read_csv(nad_file, header=0, converters={ 'Order Submission Date': to_datetime, 'Requirement Due Date': to_datetime }) next_action_date.rename(columns={'Email Address': 'Email'}, inplace=True) # Drop all but earliest next requirement next_action_date.sort_values(by='Requirement Due Date').drop_duplicates( subset='Email', keep='first', inplace=True) # Put back as string next_action_date['Requirement Due Date'] = next_action_date[ 'Requirement Due Date'].apply(lambda x: to_string(x)) # Get the latest student list students = pd.read_excel(dpu.get_latest(FL.students, 'Student List'), header=0, converters={ 'Emplid': str, 'Admit Term': str, 'Latest Term Enrl': str, 'Run Term': str, }) students.drop_duplicates(subset='Emplid', inplace=True) # Get the faculty list faculty = pd.read_excel(os.path.join(FL.faculty, 'Employee List.xlsx'), header=0, converters={ 'Empl ID': str, }) # Ignore all but necessary faculty columns faculty = faculty[[ 'Empl ID', 'Last-First', 'Primary Email', 'Secondary Email', 'Cell Phone' ]] # Get term descriptions TermDescriptions = dpu.get_term_descriptions() # Get current term current_term = dpu.guess_current_term(TermDescriptions) # Figure out next term value next_term = str(int(current_term) + 5) # Get internship roster internships = dpu.get_cln(current_term, TermDescriptions) # Try to get next term's roster, if exists try: cln_2 = dpu.get_cln(next_term, TermDescriptions) internships = pd.concat(internships, cln_2) except: pass # Drop all but required information internships = internships[[ 'Term', 'Cr', 'Clinical Site', 'Unit', 'Date', 'Student ID' ]].copy(deep=True) internships = internships[internships['Cr'] == '443'] # Get schedule global schedule schedule = dpu.get_schedule(current_term, TermDescriptions) # Get clinical roster roster = clean_student_roster(current_term, internships) # Merge with student data roster = pd.merge(roster, students[[ 'Emplid', 'Last Name', 'First Name', 'Maj Desc', 'Campus', 'Email', 'Best Phone' ]], how='left', on='Emplid') # Combine with faculty data # List of the required columns req_list = ['Last-First', 'Primary Email', 'Secondary Email', 'Cell Phone'] # Naming convention for suffixes name_con = ['1_curr', '2_curr', '1_next', '2_next'] # Iterate through suffixes (i.e., through instructors) for suffix in name_con: # Create new column names inst = 'Instructor' + '_' + suffix new_cols = [inst + ' ' + x for x in req_list] # Apply search function roster[new_cols] = roster.apply(instructor_contact_info, axis=1, args=(suffix, faculty, req_list, schedule)) # Drop Faculty ID Fields id_fields = ['Faculty_ID_' + suffix for suffix in name_con] roster.drop(labels=id_fields, axis=1, inplace=True) # Combine with schedule data # List of the required columns req_list = ['Clinical Site', 'Unit'] # Iterate through suffixes for suffix in name_con: # Create new column names new_cols = [x + '_' + suffix for x in req_list] # Apply search function roster[new_cols] = roster.apply(clinical_info, axis=1, args=(suffix, req_list, schedule, internships)) # Gather historical student data historical_students = get_historical_student_data(FL.hist_students, students) # Get a faculty roster for health_req report faculty_roster = clean_faculty_roster(current_term) # Merge with faculty contact info faculty_roster = pd.merge(faculty_roster, faculty, left_on='Emplid', right_on='Empl ID') # Separate out names faculty_roster['Last Name'] = faculty_roster['Last-First'].apply( lambda x: x.split(', ')[0]) faculty_roster['First Name'] = faculty_roster['Last-First'].apply( lambda x: x.split(', ')[1]) # Collection of tracker names all_trackers = np.concatenate( (compliant_curr['To-Do List Name'].unique(), noncompliant_curr['To-Do List Name'].unique())) all_trackers = np.unique(all_trackers) # Breakdown into types dna_trackers = [] student_trackers = [] faculty_trackers = [] for tracker in all_trackers: if 'Disclosure & Authorization' in tracker: dna_trackers.append(tracker) elif 'DE34' in tracker: faculty_trackers.append(tracker) elif 'DE69' in tracker: student_trackers.append(tracker) '''Here we attempt to connect all students in the clinical roster with an account in Castle Branch. To do so, we make a dictionary lookup. # dict[Emplid] = (Last Name, First Name, Email) ''' cb_to_dpu = {} # Attempt to match students, starting with full accounts # Sometimes the dna account is all we get, even though they have full roster.apply( match_students, axis=1, args=(noncompliant_curr[noncompliant_curr['To-Do List Name'].isin( student_trackers)], cb_to_dpu), historic=historical_students) roster.apply(match_students, axis=1, args=(compliant_curr[compliant_curr['To-Do List Name'].isin( student_trackers)], cb_to_dpu), historic=historical_students) roster.apply(match_students, axis=1, args=(noncompliant_curr[ noncompliant_curr['To-Do List Name'].isin(dna_trackers)], cb_to_dpu)) roster.apply(match_students, axis=1, args=(compliant_curr[compliant_curr['To-Do List Name'].isin( dna_trackers)], cb_to_dpu)) # Faculty matching cb_to_fac = {} faculty_roster.apply( match_faculty, axis=1, args=(noncompliant_curr[noncompliant_curr['To-Do List Name'].isin( faculty_trackers)], cb_to_fac)) faculty_roster.apply( match_faculty, axis=1, args=(compliant_curr[compliant_curr['To-Do List Name'].isin( faculty_trackers)], cb_to_fac)) faculty_roster.apply( match_faculty, axis=1, args=(noncompliant_curr[noncompliant_curr['To-Do List Name'].isin( student_trackers)], cb_to_fac)) faculty_roster.apply( match_faculty, axis=1, args=(compliant_curr[compliant_curr['To-Do List Name'].isin( student_trackers)], cb_to_fac)) # New column names fields = [ 'Changed Since ' + prev_date, 'Compliant', 'Requirements Incomplete', 'Next Due', 'Next Due Date' ] # Gather compliance status roster[fields] = roster.apply(determine_status, axis=1, args=(cb_to_dpu, noncompliant_curr, compliant_curr, noncompliant_changelog, compliant_changelog, student_trackers, dna_trackers, next_action_date), account='student') # Gather compliance status faculty_roster[fields] = faculty_roster.apply( determine_status, axis=1, args=(cb_to_fac, noncompliant_curr, compliant_curr, noncompliant_changelog, compliant_changelog, faculty_trackers, student_trackers, next_action_date), account='faculty') # Archive old reports that were created by this script for cr_report in ['student_report', 'faculty_report']: dpu.archive_old_reports(FL.health_req_report, cr_report, 'Archived') # Archive old reports downloaded from Castle Branch for dl_report in ['Compliant', 'Noncompliant', 'Next_Action_Date']: dpu.archive_old_reports(FL.health_req_cb_downloads, dl_report, 'Archive', keep_min=3) # Gather column names faculty_cols, student_cols = prepare_columns(prev_date) # Output to file date_of_current = noncompliant_files[0].rstrip('.csv')[-10:] date_of_current = datetime.strptime(date_of_current, '%Y-%m-%d') output_report(roster, student_cols, 'student_report', date_of_current, FL.health_req_report) output_report(faculty_roster, faculty_cols, 'faculty_report', date_of_current, FL.health_req_report)
def main(term): '''Main function call.''' # Initialize File Locator FL = FileLocator() # Gather term descriptions TermDescriptions = dpu.get_term_descriptions() # If term not given, guess if not term: term = dpu.guess_current_term(TermDescriptions) # Gather faculty Faculty = dpu.get_employee_list() Faculty.rename(columns={ 'Empl ID': 'Faculty ID', 'Last Name': 'Faculty Last Name', 'First Name': 'Faculty First Name', 'Last-First': 'Faculty Full Name', 'Primary Email': 'Faculty Primary Email', 'Secondary Email': 'Faculty Secondary Email', 'Cell Phone': 'Faculty Phone' }, inplace=True) # Gather student list students = dpu.get_student_list() students.rename(columns={ 'Emplid': 'Student ID', 'Student Name': 'Student Full Name', 'Last Name': 'Student Last Name', 'First Name': 'Student First Name', 'Email': 'Student Email', 'Best Phone': 'Student Phone' }, inplace=True) # Gather schedule schedule = dpu.get_schedule(term, TermDescriptions) # Filter schedule schedule = schedule[schedule['Program'].isin(['MENP', 'RFU'])] # Gather Roster roster = dpu.get_student_roster() roster.rename(columns={'Faculty_ID': 'Faculty ID'}, inplace=True) # Filter roster cln_types = ['PRA', 'CLN'] MENP_courses = schedule['Cr'].unique().tolist() roster = roster[(roster['Term'] == term) & (roster['Role'] == 'PI') & (roster['Cr'].isin(MENP_courses)) & ((roster['Type'].isin(cln_types)) | ((roster['Cr'] == '301') & (roster['Type'] == 'LAB')))].copy(deep=True) # Takes care of 301 issue (due to changing course times) roster = roster.sort_values( by=['Faculty ID', 'Start Date'], ascending=[True, False]).drop_duplicates( subset=['Term', 'Student ID', 'Cr', 'Sec']).copy(deep=True) # Gather string-formatted and concatenated dates and times roster[['Dates', 'Times']] = roster.apply(apply_dates_times, axis=1) # Drop Unneeded roster.drop(labels=[ 'Student Name', 'Student Major', 'Subject', 'Type', 'Class Nbr', 'Role', 'Mode', 'Start Date', 'End Date', 'Pat', 'Mtg Start', 'Mtg End' ], axis=1, inplace=True) # Merge together roster = roster.merge(schedule[[ 'Cr', 'Sec', 'Title', 'Clinical Site', 'Unit', 'Max Cap', 'Confirmed' ]], how='left', on=['Cr', 'Sec']) roster = roster.merge(students[[ 'Student ID', 'Student Last Name', 'Student First Name', 'Student Full Name', 'Student Email', 'Student Phone', 'Campus' ]], how='left', on='Student ID') roster = roster.merge(Faculty[[ 'Faculty ID', 'Faculty Last Name', 'Faculty First Name', 'Faculty Full Name', 'Faculty Primary Email', 'Faculty Secondary Email', 'Faculty Phone' ]], how='left', on='Faculty ID') # Column names and order column_names = [ 'Term', 'Campus', 'Cr', 'Sec', 'Clinical Site', 'Unit', 'Dates', 'Times', 'Student ID', 'Student Last Name', 'Student First Name', 'Student Full Name', 'Student Email', 'Student Phone', 'Faculty ID', 'Faculty Last Name', 'Faculty First Name', 'Faculty Full Name', 'Faculty Primary Email', 'Faculty Secondary Email', 'Faculty Phone', 'Title', 'Max Cap', 'Confirmed' ] # Gather date date_of_report = datetime.strptime( dpu.get_latest(FL.rosters, 'NSG_STDNT_ROSTER').rstrip('.xlsx')[-10:], '%Y-%m-%d') # Ensure Output path starting_path = FL.cln_roster # Gather academic year and quarter ay = TermDescriptions[TermDescriptions['Term'] == term]['Academic Year'].item() q = TermDescriptions[TermDescriptions['Term'] == term]['Quarter'].item() # Update file path output_path = os.path.join(starting_path, ay, q) dpu.ensure_dir(output_path) # Output file output_report(roster, column_names, 'Clinical Roster', date_of_report, output_path)
def main(max_year, min_year): '''Main function.''' FL = FileLocator() today = datetime.today() # If the user did not pass a max_year, use current year if not max_year: max_year = str(today.max_year) # Gather list of yearly IL pass rates il_path = os.path.abspath( os.path.join(os.sep, FL.nclex, 'Illinois Yearly Pass Rates for All Schools', 'CompetitorPassRates.xlsx')) IL_Competitors = pd.read_excel(il_path, sheet_name='Sheet1', header=0) # DPU NCLEX pass data f_path = os.path.abspath(os.path.join(os.sep, FL.nclex, 'NCLEX.xlsx')) NCLEX = pd.read_excel(f_path, header=0, converters={ 'Empl ID': str, 'Year': str }) #Fill first zero where needed NCLEX['Empl ID'] = NCLEX['Empl ID'].str.zfill(7) #Drop unnecessary fields NCLEX.drop(['Last Name', 'First Name', 'Time Delivered', 'Candidate ID'], axis=1, inplace=True) #Add days elapsed since graduation NCLEX['Date Delivered'] = pd.to_datetime(NCLEX['Date Delivered']) NCLEX['Days Elapsed'] = NCLEX['Date Delivered'] - NCLEX['Graduation Date'] NCLEX['Days Elapsed'] = NCLEX['Days Elapsed'].dt.days # Standardize Result NCLEX['Result'] = NCLEX['Result'].map(lambda x: x.lower()) # Remove repeat test-takers NCLEX = NCLEX[NCLEX['Repeater'] == 'No'] # Read Grad Data g_path = os.path.abspath(os.path.join(os.sep, FL.grad)) f = dpu.get_latest(g_path, 'NSG_GRAD_REVISED') Grad_data = pd.read_excel(f, skiprows=0, header=1, na_values='nan', converters={ 'ID': str, 'Admit Term': str, 'Compl Term': str }) # Drop students in the wrong degree program (students who take more than # one program will be duplicated unnecessarily). Grad_data = Grad_data[Grad_data['Degree'] == 'MS'] Grad_data = Grad_data[Grad_data['Acad Plan'].isin( ['MS-NURSING', 'MS-GENRNSG'])] Grad_data = Grad_data[Grad_data['Sub-Plan'] != 'ANESTHESIS'] # Determine number of quarters between admit and completion Grad_data['Qtrs to Grad'] = Grad_data.apply( lambda x: qtrs(x['Admit Term'], x['Compl Term']), axis=1) # Combine NCLEX and Graduates into Temp dataframe NCLEX_df = pd.merge(NCLEX[[ 'Empl ID', 'Campus', 'Result', 'Days Elapsed', 'Year', 'Quarter', 'Graduation Date' ]], Grad_data[['ID', 'GPA', 'Qtrs to Grad', 'Compl Term']], how='left', left_on='Empl ID', right_on='ID', sort=True, copy=True) # Drop degree and ID fields NCLEX_df = NCLEX_df.drop(['ID'], axis=1) '''We do not have the testing dates for students who take NCLEX out of state. There are also a few oddities, where students test before they technically receive their degrees. To avoid these outlier cases from affecting our data, we will impute all NaN, 0, and negative values using the mean of the group as a whole, rounded to the nearest unit value.''' elapsed = round(NCLEX_df.mean()['Days Elapsed'], 0) NCLEX_df['Days Elapsed'].fillna(elapsed, inplace=True) NCLEX_df.loc[NCLEX_df['Days Elapsed'] <= 0, 'Days Elapsed'] = elapsed # If the user did not pass a min_year, use earliest year in data if not min_year: all_years = NCLEX_df['Year'].unique().tolist() all_years.sort() min_year = all_years[0] # Build a list of all years to consider year_list_int = np.arange(int(min_year), int(max_year) + 1) year_list_str = [str(x) for x in year_list_int] # Build all the graphs graphs = [ historical_line(IL_Competitors, "Year", "Pass Rate", "Master's Entry Program", groupby_vals=['DePaul University'], show_vals='all', y_lim=[70, 101], years=year_list_int), historical_line(IL_Competitors, "Year", "Pass Rate", "Master's Entry Program", y_lim=[70, 101], years=year_list_int), scatter_trend(IL_Competitors, 'Year', 'Pass Rate', "Master's Entry Program", title="Yearly Pass Rates of IL Master's Entry Programs", groupby_vals=['DePaul University', 'Rush University'], groupby_colors=['#396E93', '#80AA69'], y_lim=[70, 101], x_vals=year_list_int), stacked_bar_NCLEX(IL_Competitors, school_list=['DePaul University', 'Rush University'], year_list=year_list_int), histogram_NCLEX(NCLEX_df, 'GPA', ignore_outliers=False), ANOVA_boxplot(NCLEX_df, 'GPA', 'Result'), histogram_NCLEX(NCLEX_df, 'Days Elapsed', ignore_outliers=True), ANOVA_boxplot(NCLEX_df, 'Days Elapsed', 'Result', ignore_outliers=True) ] # Open a PDF file o_path = os.path.abspath( os.path.join(os.sep, FL.nclex, 'Reports', 'NCLEX_Charts {}.pdf'.format(today.strftime('%Y-%m-%d')))) with PdfPages(o_path) as pdf: # Write all the figures to file for graph in graphs: pdf.savefig(graph) plt.close(graph) #Set the file's metadata via the PdfPages object: d = pdf.infodict() d['Title'] = 'NCLEX Charts' d['Author'] = os.getlogin() d['ModDate'] = today
def main(fy): '''Main function.''' # Call to FileLocator class FL = FileLocator() # Set as global variables (used by many charts) global TermDescriptions global course_types_abbr global program_types_abbr #Read in term descriptions TermDescriptions = dpu.get_term_descriptions() # Simplify years for easier access years = TermDescriptions[['Academic Year', 'Fiscal Year']].copy(deep=True) years.drop_duplicates(subset=['Fiscal Year'], keep='first', inplace=True) #Set abbreviations for course types course_types_abbr = {'LEC': 'Lc', 'LAB': 'Lb', 'PRA': 'Pr', 'COORD': 'Co'} #Set abbreviations for programs program_types_abbr = { 'MENP': 'MENP at LPC', 'RFU': 'MENP at RFU', 'DNP': 'DNP', 'RN to MS': 'RN to MS', None: 'All' } # Create a dictionary to store data temporarily sched_dict = {} # If user supplies a specific Fiscal Year if fy: # Ensure that fiscal year follows appropriate formatting if re.match(r"\d{2}", fy): fy = "FY '" + str(fy) elif re.match(r"'\d{2}", fy): fy = "FY " + fy elif re.match(r"FY '\d{2}", fy): pass else: raise Exception( "Fiscal Year must be in appropriate format, e.g. FY '18.") # Determine academic year from fiscal year try: ay = years[years['Fiscal Year'] == fy]['Academic Year'].item() except: print("Must provide a valid Fiscal Year") # If user does not supply Fiscal Year as an argument... else: # Get all directories that match regex subfolders = [ f.name for f in os.scandir('W:\\csh\\Nursing\\Schedules') if f.is_dir() and re.match(r'\d{4}-\d{4}', f.name) ] # Sort the directories subfolders.sort() # Assume correct academic year is the last one ay = subfolders[-1] # Determine fiscal year from academic year fy = years[years['Academic Year'] == ay]['Fiscal Year'].item() # Collect data # Convert fy to integer for mathematical checks fy_int = int(fy[-2:]) counter = 0 # The lowest FY for which data is available is FY '15 while fy_int >= 15 and counter <= 5: # Create nested dictionary sched_dict[fy] = {} # Build a temporary path to the schedule sched_dict[fy]['folder'] = os.path.join(FL.schedule, ay) # Get the latest build of the schedule document sched_dict[fy]['file_path'] = dpu.get_latest(sched_dict[fy]['folder'], 'Fiscal Schedule', date_format='%m-%d-%Y', ignore_suffix='(2)') # Get the schedule and faculty data sched_dict[fy]['schedule'], sched_dict[fy]['faculty'] = cat_sched( sched_dict[fy]['file_path']) # Increment Fiscal Year and counter fy_int -= 1 counter += 1 # update fy and ay fy = "FY '" + str(fy_int) ay = years[years['Fiscal Year'] == fy]['Academic Year'].item() # Gather a sorted list of fiscal years fiscal_years = list(sched_dict.keys()) fiscal_years.sort() #Make List of dataframes FYHistory = [sched_dict[x]['schedule'] for x in fiscal_years] #Concatenate Recent FY Data FYConcat = pd.concat(FYHistory, ignore_index=True) # Output charts and faculty schedule for highest two fiscal years for year in fiscal_years[-2:]: chart_wrapper(sched_dict[year]['schedule'], sched_dict[year]['faculty'], FYHistory, sched_dict[year]['folder']) output_faculty_schedule(FL.faculty_workload, sched_dict, FYConcat, fiscal_years)