Koolaidrain

hackNY/analyze.py

Mar 27th, 2023
295
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 23.05 KB | None | 0 0
  1. #!/usr/bin/python3
  2.  
  3. import csv
  4. import math
  5. import numpy
  6. import pandas
  7. import statistics
  8. import sys
  9. from collections import defaultdict
  10. from typing import DefaultDict, Dict, List, Optional, Tuple, Union
  11.  
  12.  
  13. # recommendation related constants
  14. MAX_RECOMMENDATIONS_PER_APPLICANT = 3
  15. # review related constants
  16. REVIEW_ROUND_ID = 1
  17. MAX_REVIEWERS_PER_APPLICANT = 5
  18. MIN_REVIEWERS_PER_APPLICANT = 2
  19. # interview related constants
  20. INTERVIEW_ROUND_ID = 2
  21. MAX_INTERVIEWERS_PER_APPLICANT = 1
  22. MIN_INTERVIEWERS_PER_APPLICANT = 1
  23. # relative file paths
  24. APPLICANT_DATA_CSV_PATH = "output/applicant_data.csv"
  25. APPLICANT_INSIGHTS_GENDER_CSV_PATH = "output/applicant_insights_gender.csv"
  26. APPLICANT_INSIGHTS_GRAD_YEAR_CSV_PATH = "output/applicant_insights_grad_year.csv"
  27. APPLICANT_INSIGHTS_SCHOOL_CSV_PATH = "output/applicant_insights_school.csv"
  28. REVIEWER_DATA_CSV_PATH = "output/reviewer_data.csv"
  29. INTERVIEWER_DATA_CSV_PATH = "output/interviewer_data.csv"
  30. # misc constants
  31. GENDER_ALIASES = {
  32. "Male": ["m", "male", "man"],
  33. "Female": ["f", "female", "woman"],
  34. "Nonbinary": ["nb", "non-binary", "nb", numpy.nan],
  35. }
  36. # invert gender_aliases dict
  37. ALIASES_GENDER = {}
  38. for gender, aliases in GENDER_ALIASES.items():
  39. for alias in aliases:
  40. ALIASES_GENDER[alias] = gender
  41. HELP_TEXT = """
  42. I need one input file.
  43. 1. applicants.tsv with headers: all visible columns from the export view on Embark
  44. """
  45. # question constants
  46. INTERNSHIP_EXISTS_QUESTION = "If you have already secured a summer internship, please specify the compan
  47. y name and the start/end dates of your internship here."
  48. INTERNSHIP_PLAN_QUESTION = "If you have NOT already secured a summer internship, please explain your cur
  49. rent plan to secure one here."
  50.  
  51.  
  52. def normalize_score(score: Union[float, str]) -> float:
  53. # scores could be float:numpy.nan or str:"3: Good"
  54. if isinstance(score, str):
  55. return float(score[0])
  56. return score
  57.  
  58.  
  59. def get_stdev(variance: float) -> float:
  60. # could be -1.0 (no score exists)
  61. if variance < 0:
  62. return -1.0
  63. return math.sqrt(variance)
  64.  
  65.  
  66. def get_mean(values: List[float]) -> float:
  67. if values and len(values) > 1:
  68. return statistics.mean(values)
  69. elif values:
  70. return values[0]
  71. else:
  72. return numpy.nan
  73.  
  74.  
  75. def get_variance(values: List[float]) -> float:
  76. if values and len(values) > 1:
  77. return statistics.variance(values)
  78. else:
  79. return numpy.nan
  80.  
  81.  
  82. class Recommendation:
  83. def __init__(self, applicant: str, recommender_id: int, series: pandas.Series):
  84. prefix = f"Rec {recommender_id}"
  85. self.applicant = applicant
  86. self.recommender = series[f"{prefix} Full Name"]
  87.  
  88. @property
  89. def exists(self) -> bool:
  90. return isinstance(self.recommender, str)
  91.  
  92.  
  93. class Review:
  94. def __init__(self, applicant: str, reviewer_id: int, series: pandas.Series):
  95. prefix = f"Rd {REVIEW_ROUND_ID} R{reviewer_id}"
  96. self.applicant = applicant
  97. self.reviewer = series[f"{prefix} Name"]
  98. self.status = series[f"{prefix} Status"]
  99. self.technical_score = normalize_score(series[f"{prefix} Technical Competency Score"])
  100. self.community_score = normalize_score(series[f"{prefix} Community Involvement Score"])
  101.  
  102. @property
  103. def exists(self) -> bool:
  104. return isinstance(self.reviewer, str)
  105.  
  106. @property
  107. def is_complete(self) -> bool:
  108. return bool(
  109. self.status == "Completed"
  110. and self.technical_score is not numpy.nan
  111. and self.community_score is not numpy.nan
  112. )
  113.  
  114.  
  115. class Interview:
  116. def __init__(self, applicant: str, interviewer_id: int, series: pandas.Series):
  117. prefix = f"Rd {INTERVIEW_ROUND_ID} R{interviewer_id}"
  118. self.applicant = applicant
  119. self.interviewer = series[f"{prefix} Name"]
  120. self.status = series[f"{prefix} Status"]
  121. self.fit_score = normalize_score(series[f"{prefix} Candidate Fit Score"])
  122. self.fit_confidence = normalize_score(series[f"{prefix} Candidate Fit Confidence Rating"])
  123.  
  124. @property
  125. def exists(self) -> bool:
  126. return isinstance(self.interviewer, str)
  127.  
  128. @property
  129. def is_complete(self) -> bool:
  130. return bool(
  131. self.status == "Completed"
  132. and self.fit_score is not numpy.nan
  133. and self.fit_confidence is not numpy.nan
  134. )
  135.  
  136.  
  137. class Applicant:
  138. def __init__(self, series: pandas.Series):
  139. self.series = series
  140.  
  141. @property
  142. def name(self):
  143. first_name = self.series["First Name"]
  144. last_name = self.series["Last Name"]
  145. return f"{first_name} {last_name}"
  146.  
  147. @property
  148. def internship_response(self):
  149. internship_exists_response = self.series[INTERNSHIP_EXISTS_QUESTION]
  150. internship_plan_response = self.series[INTERNSHIP_PLAN_QUESTION]
  151. if internship_exists_response is numpy.nan:
  152. return internship_plan_response
  153. else:
  154. return internship_exists_response
  155.  
  156. @property
  157. def email(self):
  158. return self.series["E-mail address"]
  159.  
  160. @property
  161. def school(self):
  162. return self.series["University/College"]
  163.  
  164. @property
  165. def gender(self):
  166. return (
  167. self.series["Gender"].lower()
  168. if isinstance(self.series["Gender"], str)
  169. else numpy.nan
  170. )
  171.  
  172. @property
  173. def race_ethnicity(self):
  174. return self.series["Race / Ethnicity"]
  175.  
  176. @property
  177. def graduation_year(self):
  178. # exported format is XX-XX-20XX
  179. graduation_date = self.series["Graduation Date"]
  180. return graduation_date[-4:]
  181.  
  182. @property
  183. def reviewers(self):
  184. return [
  185. " ".join(reversed(str(self.series[f"Rd 1 R{i} Name"]).split(", ")))
  186. for i in range(1, 1 + MAX_REVIEWERS_PER_APPLICANT)
  187. ]
  188.  
  189. @property
  190. def recommendations(self) -> List[Recommendation]:
  191. recommendations = [
  192. Recommendation(self.name, i + 1, self.series)
  193. for i in range(MAX_RECOMMENDATIONS_PER_APPLICANT)
  194. ]
  195. return [r for r in recommendations if r.exists]
  196.  
  197.  
  198. @property
  199. def reviews(self) -> List[Review]:
  200. reviews = [
  201. Review(self.name, i + 1, self.series)
  202. for i in range(MAX_REVIEWERS_PER_APPLICANT)
  203. ]
  204. return [r for r in reviews if r.exists]
  205.  
  206. @property
  207. def interviews(self) -> List[Interview]:
  208. interviews = [
  209. Interview(self.name, i + 1, self.series)
  210. for i in range(MAX_INTERVIEWERS_PER_APPLICANT)
  211. ]
  212. return [i for i in interviews if i.exists]
  213.  
  214. @property
  215. def complete_reviews(self) -> List[Review]:
  216. return [review for review in self.reviews if review.is_complete]
  217.  
  218. @property
  219. def complete_interviews(self) -> List[Interview]:
  220. return [interview for interview in self.interviews if interview.is_complete]
  221.  
  222. @property
  223. def technical_scores(self) -> List[float]:
  224. return [review.technical_score for review in self.complete_reviews]
  225.  
  226. @property
  227. def community_scores(self) -> List[float]:
  228. return [review.community_score for review in self.complete_reviews]
  229.  
  230. @property
  231. def technical_moments(self) -> Tuple[float, float]:
  232. if not self.is_reviewed:
  233. return (-1.0, -1.0)
  234. return (
  235. get_mean(self.technical_scores),
  236. get_variance(self.technical_scores),
  237. )
  238.  
  239. @property
  240. def community_moments(self) -> Tuple[float, float]:
  241. if not self.is_reviewed:
  242. return (-1.0, -1.0)
  243. return (
  244. get_mean(self.community_scores),
  245. get_variance(self.community_scores),
  246. )
  247.  
  248. @property
  249. def overall_moments(self) -> Tuple[float, float]:
  250. if not self.is_reviewed:
  251. return (-1.0, -1.0)
  252. return numpy.add(self.technical_moments, self.community_moments) / 2
  253.  
  254.  
  255. @property
  256. def is_reviewed(self) -> bool:
  257. return len(self.complete_reviews) >= MIN_REVIEWERS_PER_APPLICANT
  258.  
  259. @property
  260. def fit_scores(self) -> List[float]:
  261. return [interview.fit_score for interview in self.complete_interviews]
  262.  
  263. @property
  264. def fit_confidences(self) -> List[float]:
  265. return [interview.fit_confidence for interview in self.complete_interviews]
  266.  
  267. @property
  268. def fit_score_moments(self) -> List[float]:
  269. if not self.is_interviewed:
  270. return (-1.0, -1.0)
  271. return (
  272. get_mean(self.fit_scores),
  273. get_variance(self.fit_confidences),
  274. )
  275.  
  276. @property
  277. def fit_confidence_moments(self) -> List[float]:
  278. if not self.is_interviewed:
  279. return (-1.0, -1.0)
  280. return (
  281. get_mean(self.fit_confidences),
  282. get_variance(self.fit_confidences),
  283. )
  284.  
  285. @property
  286. def is_interviewed(self) -> bool:
  287. return len(self.complete_interviews) >= MIN_INTERVIEWERS_PER_APPLICANT
  288.  
  289. def to_dict(self) -> Dict:
  290. technical_mean, technical_variance = self.technical_moments
  291. community_mean, community_variance = self.community_moments
  292. fit_score_mean, fit_score_variance = self.fit_score_moments
  293. fit_confidence_mean, fit_confidence_variance = self.fit_confidence_moments
  294. return {
  295. "Name": self.name,
  296. "Email": self.email,
  297. "Gender": self.gender,
  298. "Race/Ethnicity": self.race_ethnicity,
  299. "Graduation Year": self.graduation_year,
  300. "Internship Response": self.internship_response,
  301. "# Recommenders": len(self.recommendations),
  302. "# Complete Reviews": len(self.complete_reviews),
  303. "# Complete Interviews": len(self.complete_interviews),
  304. "Reviewers": "|".join(self.reviewers),
  305. "Review Technical Score: Mean": technical_mean,
  306. "Review Technical Score: Std Dev": get_stdev(technical_variance),
  307. "Review Community Score: Mean": community_mean,
  308. "Review Community Score: Std Dev": get_stdev(community_variance),
  309. "Review Overall Score: Mean": (technical_mean + community_mean) / 2,
  310. "Review Overall Score: Std Dev": get_stdev((technical_variance + community_variance) / 2),
  311. "Interviewer": self.interviews[0].interviewer if self.interviews else numpy.nan,
  312. "Interview Status": self.interviews[0].status if self.interviews else numpy.nan,
  313. "Interview Fit Score: Mean": fit_score_mean,
  314. "Interview Fit Score: Std Dev": get_stdev(fit_score_variance),
  315. "Interview Fit Confidence: Mean": fit_confidence_mean,
  316. "Interview Fit Confidence: Std Dev": get_stdev(fit_confidence_variance),
  317. }
  318.  
  319.  
  320. class Recommender:
  321. def __init__(self, name: str, recommendations: List[Recommendation]):
  322. self.name = name
  323. self.recommendations = recommendations
  324.  
  325.  
  326. class Reviewer:
  327. def __init__(self, name: str, reviews: List[Review]):
  328. self.name = name
  329. self.reviews = reviews
  330.  
  331. @property
  332. def complete_reviews(self) -> List[Review]:
  333. return [review for review in self.reviews if review.is_complete]
  334.  
  335. @property
  336. def incomplete_reviews(self) -> List[Review]:
  337. return [review for review in self.reviews if not review.is_complete]
  338.  
  339. @property
  340. def technical_scores(self) -> List[float]:
  341. return [review.technical_score for review in self.complete_reviews]
  342.  
  343. @property
  344. def community_scores(self) -> List[float]:
  345. return [review.community_score for review in self.complete_reviews]
  346.  
  347. @property
  348. def technical_moments(self) -> Tuple[float, float]:
  349. if not len(self.technical_scores):
  350. return (-1.0, -1.0)
  351. return (
  352. get_mean(self.technical_scores),
  353. get_variance(self.technical_scores),
  354. )
  355.  
  356. @property
  357. def community_moments(self) -> Tuple[float, float]:
  358. if not len(self.community_scores):
  359. return (-1.0, -1.0)
  360. return (
  361. get_mean(self.community_scores),
  362. get_variance(self.community_scores),
  363. )
  364.  
  365. def to_dict(self) -> Dict:
  366. technical_mean, technical_variance = self.technical_moments
  367. community_mean, community_variance = self.community_moments
  368. return {
  369. "Name": self.name,
  370. "# Complete Reviews": len(self.complete_reviews),
  371. "# Incomplete Reviews": len(self.incomplete_reviews),
  372. "Technical Score: Mean": technical_mean,
  373. "Technical Score: Std Dev": get_stdev(technical_variance),
  374. "Community Score: Mean": community_mean,
  375. "Community Score: Std Dev": get_stdev(community_variance),
  376. "Overall Score: Mean": (technical_mean + community_mean) / 2,
  377. "Overall Score: Std Dev": get_stdev((technical_variance + community_variance) / 2),
  378. }
  379.  
  380.  
  381. class Interviewer:
  382. def __init__(self, name: str, interviews: List[Interview]):
  383. self.name = name
  384. self.interviews = interviews
  385.  
  386. @property
  387. def complete_interviews(self) -> List[Interview]:
  388. return [interview for interview in self.interviews if interview.is_complete]
  389.  
  390. @property
  391. def incomplete_interviews(self) -> List[Review]:
  392. return [interview for interview in self.interviews if not interview.is_complete]
  393.  
  394. @property
  395. def fit_scores(self) -> List[float]:
  396. return [interview.fit_score for interview in self.complete_interviews]
  397.  
  398. @property
  399. def fit_confidences(self) -> List[float]:
  400. return [interview.fit_confidence for interview in self.complete_interviews]
  401.  
  402. @property
  403. def fit_score_moments(self) -> Tuple[float, float]:
  404. if not len(self.fit_scores):
  405. return (-1.0, -1.0)
  406. return (
  407. get_mean(self.fit_scores),
  408. get_variance(self.fit_scores),
  409. )
  410.  
  411. @property
  412. def fit_confidence_moments(self) -> Tuple[float, float]:
  413. if not len(self.fit_confidences):
  414. return (-1.0, -1.0)
  415. return (
  416. get_mean(self.fit_confidences),
  417. get_variance(self.fit_confidences),
  418. )
  419.  
  420. def to_dict(self) -> Dict:
  421. fit_score_mean, fit_score_variance = self.fit_score_moments
  422. fit_confidence_mean, fit_confidence_variance = self.fit_confidence_moments
  423. return {
  424. "Name": self.name,
  425. "# Complete Interviews": len(self.complete_interviews),
  426. "# Incomplete Interviews": len(self.incomplete_interviews),
  427. "Fit Score: Mean": fit_score_mean,
  428. "Fit Score: Std Dev": get_stdev(fit_score_variance),
  429. "Fit Confidence: Mean": fit_confidence_mean,
  430. "Fit Confidence: Std Dev": get_stdev(fit_confidence_variance),
  431. }
  432.  
  433.  
  434. def register_applicants(df: pandas.DataFrame) -> List[Applicant]:
  435. applicants = []
  436. for _row_id, series in df.iterrows():
  437. applicant = Applicant(series)
  438. applicants.append(applicant)
  439. print(f"- Registered {len(applicants)} applicants.")
  440. return applicants
  441.  
  442.  
  443. def register_recommenders(applicants: List[Applicant]) -> List[Recommender]:
  444. recommenders = []
  445. recommender_recommendations: DefaultDict[str, List[Recommendation]] = defaultdict(list)
  446. for applicant in applicants:
  447. for recommendation in applicant.recommendations:
  448. recommender_recommendations[recommendation.recommender].append(recommendation)
  449. for recommender_name, recommendations in recommender_recommendations.items():
  450. recommender = Recommender(recommender_name, recommendations)
  451. recommenders.append(recommender)
  452. print(f"- Registered {len(recommenders)} recommenders.")
  453. return recommenders
  454.  
  455.  
  456. def register_reviewers(applicants: List[Applicant]) -> List[Reviewer]:
  457. reviewers = []
  458. reviewer_reviews: DefaultDict[str, List[Review]] = defaultdict(list)
  459. for applicant in applicants:
  460. for review in applicant.reviews:
  461. reviewer_reviews[review.reviewer].append(review)
  462. for reviewer_name, reviews in reviewer_reviews.items():
  463. reviewer = Reviewer(reviewer_name, reviews)
  464. reviewers.append(reviewer)
  465. print(f"- Registered {len(reviewers)} reviewers.")
  466. return reviewers
  467.  
  468.  
  469. def register_interviewers(applicants: List[Applicant]) -> List[Interviewer]:
  470. interviewers = []
  471. interviewer_interviews: DefaultDict[str, List[Interview]] = defaultdict(list)
  472. for applicant in applicants:
  473. for interview in applicant.interviews:
  474. interviewer_interviews[interview.interviewer].append(interview)
  475. for interviewer_name, interviews in interviewer_interviews.items():
  476. interviewer = Interviewer(interviewer_name, interviews)
  477. interviewers.append(interviewer)
  478. print(f"- Registered {len(interviewers)} interviewers.")
  479. return interviewers
  480.  
  481.  
  482. def generate_applicant_key_insights(
  483. applicants: List[Applicant], key_name: str, alias_key_lookup: Optional[Dict] = None
  484. ) -> Dict[str, Dict[str, float]]:
  485. applicant_key_insights = {}
  486. # bucket all review/interview scores by key (school, grad year, gender, etc.)
  487. # key must be a property of the Applicant class
  488. key_freq = defaultdict(int)
  489. technical_scores = defaultdict(list)
  490. community_scores = defaultdict(list)
  491. fit_scores = defaultdict(list)
  492. fit_confidences = defaultdict(list)
  493. for applicant in applicants:
  494. key = getattr(applicant, key_name)
  495. if alias_key_lookup:
  496. key = alias_key_lookup.get(key)
  497. key_freq[key] += 1
  498. technical_scores[key].extend(applicant.technical_scores)
  499. community_scores[key].extend(applicant.community_scores)
  500. fit_scores[key].extend(applicant.fit_scores)
  501. fit_confidences[key].extend(applicant.fit_confidences)
  502. # generate insights by key
  503. for key in key_freq.keys():
  504. review_technical_mean = get_mean(technical_scores[key])
  505. review_technical_variance = get_variance(technical_scores[key])
  506. review_community_mean = get_mean(community_scores[key])
  507. review_community_variance = get_variance(community_scores[key])
  508. review_overall_mean = (review_technical_mean + review_community_mean) / 2
  509. review_overall_variance = (review_technical_variance + review_community_variance) / 2
  510. interview_fit_score_mean = get_mean(fit_scores[key]) if fit_scores[key] else -1.0
  511. interview_fit_score_variance = (
  512. get_variance(fit_scores[key]) if fit_scores[key] else -1.0
  513. )
  514. interview_fit_confidence_mean = (
  515. get_mean(fit_confidences[key]) if fit_confidences[key] else -1.0
  516. )
  517. interview_fit_confidence_variance = (
  518. get_variance(fit_confidences[key]) if fit_confidences[key] else -1.0
  519. )
  520. applicant_key_insights[key] = {
  521. "Review Technical Score: Mean": review_technical_mean,
  522. "Review Technical Score: Std Dev": get_stdev(review_technical_variance),
  523. "Review Community Score: Mean": review_community_mean,
  524. "Review Community Score: Std Dev": get_stdev(review_community_variance),
  525. "Review Overall Score: Mean": review_overall_mean,
  526. "Review Overall Score: Std Dev": get_stdev(review_overall_variance),
  527. "Interview Fit Score: Mean": interview_fit_score_mean,
  528. "Interview Fit Score: Std Dev": get_stdev(interview_fit_score_variance),
  529. "Interview Fit Confidence: Mean": interview_fit_confidence_mean,
  530. "Interview Fit Confidence: Std Dev": get_stdev(interview_fit_confidence_variance),
  531. }
  532. return [
  533. format_dict({key_name.capitalize(): key, "Count": key_freq[key], **insights})
  534. for key, insights in applicant_key_insights.items()
  535. ]
  536.  
  537.  
  538. def generate_applicant_insights(applicants: List[Applicant]) -> List[Dict]:
  539. return [format_dict(a.to_dict()) for a in applicants]
  540.  
  541.  
  542. def generate_reviewer_insights(reviewers: List[Reviewer]) -> List[Dict]:
  543. return [format_dict(r.to_dict()) for r in reviewers]
  544.  
  545.  
  546. def generate_interviewer_insights(interviewers: List[Interviewer]) -> List[Dict]:
  547. return [format_dict(r.to_dict()) for r in interviewers]
  548.  
  549.  
  550. def write_to_csv(
  551. filename: str, entry_dicts: List[Dict], sort_headers: Optional[List[str]] = None
  552. ) -> None:
  553. if not entry_dicts:
  554. print(f"- Cannot write to {filename}: entry_dicts is empty.")
  555. return
  556. if sort_headers:
  557. entry_dicts = sorted(
  558. entry_dicts, reverse=True, key=lambda d: tuple(d.get(h) for h in sort_headers)
  559. )
  560. with open(filename, 'w', newline='') as csvfile:
  561. headers = list(entry_dicts[0])
  562. writer = csv.DictWriter(csvfile, fieldnames=headers)
  563. writer.writeheader()
  564. for entry_dict in entry_dicts:
  565. writer.writerow(entry_dict)
  566.  
  567.  
  568. def format_dict(d: Dict) -> Dict:
  569. formatted_d = {}
  570. for key, value in d.items():
  571. if isinstance(value, bool):
  572. formatted_d[key] = str(value)
  573. elif isinstance(value, float):
  574. formatted_d[key] = f"{value:.2f}"
  575. else:
  576. formatted_d[key] = value
  577. return formatted_d
  578.  
  579.  
  580. def main(df: pandas.DataFrame):
  581. print("\nRegistering structs...")
  582. applicants = register_applicants(df)
  583. recommenders = register_recommenders(applicants)
  584. reviewers = register_reviewers(applicants)
  585. interviewers = register_interviewers(applicants)
  586. print("\nGenerating data + insights...")
  587. applicant_dicts = generate_applicant_insights(applicants)
  588. applicant_insights_gender = generate_applicant_key_insights(
  589. applicants, "gender", alias_key_lookup=ALIASES_GENDER
  590. )
  591. applicant_insights_grad_year = generate_applicant_key_insights(applicants, "graduation_year")
  592. applicant_insights_school = generate_applicant_key_insights(applicants, "school")
  593. reviewer_dicts = generate_reviewer_insights(reviewers)
  594. interviewer_dicts = generate_interviewer_insights(interviewers)
  595. print("\nWriting to CSVs...")
  596. write_to_csv(
  597. APPLICANT_DATA_CSV_PATH,
  598. applicant_dicts,
  599. sort_headers=["Review Overall Score: Mean"],
  600. )
  601. write_to_csv(
  602. APPLICANT_INSIGHTS_GENDER_CSV_PATH,
  603. applicant_insights_gender,
  604. sort_headers=["Review Overall Score: Mean"]
  605. )
  606. write_to_csv(
  607. APPLICANT_INSIGHTS_GRAD_YEAR_CSV_PATH,
  608. applicant_insights_grad_year,
  609. sort_headers=["Review Overall Score: Mean"]
  610. )
  611. write_to_csv(
  612. APPLICANT_INSIGHTS_SCHOOL_CSV_PATH,
  613. applicant_insights_school,
  614. sort_headers=["Review Overall Score: Mean"],
  615. )
  616. write_to_csv(
  617. REVIEWER_DATA_CSV_PATH,
  618. reviewer_dicts,
  619. sort_headers=["Overall Score: Mean"],
  620. )
  621. write_to_csv(
  622. INTERVIEWER_DATA_CSV_PATH,
  623. interviewer_dicts,
  624. sort_headers=["Fit Score: Mean"],
  625. )
  626. print("\nComplete.")
  627.  
  628.  
  629. if __name__ == "__main__":
  630. if len(sys.argv) < 2:
  631. print(HELP_TEXT)
  632. sys.exit(1)
  633. df = pandas.read_csv(sys.argv[1], sep="\t")
  634. main(df)
  635.  
Advertisement
Add Comment
Please, Sign In to add comment