ltc-code 0.2.14__tar.gz → 0.2.16__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {ltc_code-0.2.14 → ltc_code-0.2.16}/PKG-INFO +3 -3
  2. {ltc_code-0.2.14 → ltc_code-0.2.16}/pyproject.toml +3 -3
  3. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/.DS_Store +0 -0
  4. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/.DS_Store +0 -0
  5. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/build_nsc_outcomes.py +81 -25
  6. ltc_code-0.2.16/src/ltc_code/nsc/raw/.DS_Store +0 -0
  7. ltc_code-0.2.16/src/ltc_code/nsc/raw/chetty/mrc_table11.dta +0 -0
  8. {ltc_code-0.2.14 → ltc_code-0.2.16}/README.md +0 -0
  9. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/aspire.py +0 -0
  10. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/check_cmo_apps.do +0 -0
  11. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/christel_house.py +0 -0
  12. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/democracy_prep.py +0 -0
  13. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/green_dot.py +0 -0
  14. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/helpers.py +0 -0
  15. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/ilt.py +0 -0
  16. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/kipp_nj.py +0 -0
  17. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/main.py +0 -0
  18. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/mappings.py +0 -0
  19. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/rocketship.py +0 -0
  20. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260614_new_build_scripts_update/yes_prep.py +0 -0
  21. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/aspire.py +0 -0
  22. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/christel_house.py +0 -0
  23. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/democracy_prep.py +0 -0
  24. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/green_dot.py +0 -0
  25. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/ilt.py +0 -0
  26. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/kipp.py +0 -0
  27. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/kipp_nj.py +0 -0
  28. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/rocketship.py +0 -0
  29. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260630_census_disclosure/yes_prep.py +0 -0
  30. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/BALANCE.do +0 -0
  31. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/FS.do +0 -0
  32. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/ITT.do +0 -0
  33. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/TOT.do +0 -0
  34. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/apps_helpers.py +0 -0
  35. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/harmony.py +0 -0
  36. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260706_ceprscripts/main.py +0 -0
  37. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260712_uncommon_scripts/main.py +0 -0
  38. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260712_uncommon_scripts/mappings.py +0 -0
  39. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/20260712_uncommon_scripts/uncommon.py +0 -0
  40. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/__init__.py +0 -0
  41. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/aspire.py +0 -0
  42. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/check_cmo_apps.do +0 -0
  43. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/christel_house.py +0 -0
  44. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/green_dot.py +0 -0
  45. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/helpers.py +0 -0
  46. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/june13.py +0 -0
  47. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/june2.py +0 -0
  48. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/june30.py +0 -0
  49. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/june5.py +0 -0
  50. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/june7.py +0 -0
  51. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/kipp_nj.py +0 -0
  52. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/kipp_tx.py +0 -0
  53. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/main.py +0 -0
  54. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/mappings.py +0 -0
  55. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/may27.py +0 -0
  56. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/__init__.py +0 -0
  57. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/input/.gitkeep +0 -0
  58. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/naics.csv +0 -0
  59. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/naics.py +0 -0
  60. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/naics_raw.xlsx +0 -0
  61. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/output/.gitkeep +0 -0
  62. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/CREDENTIAL_LEVEL_LOOKUP_TABLE.xlsx +0 -0
  63. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/IPEDS_IC_2013.csv +0 -0
  64. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/IPEDS_IC_manual.xlsx +0 -0
  65. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/chetty/mrc_table2.dta +0 -0
  66. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/college_crosswalk.xls +0 -0
  67. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/raw/directory.dta +0 -0
  68. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/nsc/run_nsc_outcomes.py +0 -0
  69. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/polars_dates.py +0 -0
  70. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/rocketship.py +0 -0
  71. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/schema_mapping.py +0 -0
  72. {ltc_code-0.2.14 → ltc_code-0.2.16}/src/ltc_code/yes_prep.py +0 -0
@@ -1,9 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: ltc-code
3
- Version: 0.2.14
3
+ Version: 0.2.16
4
4
  Summary: Add your description here
5
- Requires-Dist: fastexcel>=0.20.2
6
- Requires-Dist: polars>=1.42.1
5
+ Requires-Dist: fastexcel>=0.16,<0.20
6
+ Requires-Dist: polars>=1.36.1,<1.42
7
7
  Requires-Dist: polars-readstat>=0.20.2
8
8
  Requires-Python: >=3.9
9
9
  Description-Content-Type: text/markdown
@@ -1,12 +1,12 @@
1
1
  [project]
2
2
  name = "ltc-code"
3
- version = "0.2.14"
3
+ version = "0.2.16"
4
4
  description = "Add your description here"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.9"
7
7
  dependencies = [
8
- "fastexcel>=0.20.2",
9
- "polars>=1.42.1",
8
+ "fastexcel>=0.16,<0.20",
9
+ "polars>=1.36.1,<1.42",
10
10
  "polars-readstat>=0.20.2",
11
11
  ]
12
12
 
@@ -43,6 +43,17 @@ CHETTY_MRC_TABLE2 = next(
43
43
  )
44
44
  # Chetty/Barron college tier lookup. Numeric tier 1/2 identifies elite colleges.
45
45
 
46
+ CHETTY_MRC_TABLE11_CANDIDATES = [
47
+ RAW_NSC / "chetty" / "mrc_table11.dta",
48
+ RAW_NSC / "mrc_table11.dta",
49
+ PACKAGE_NSC.parents[3] / "College" / "chetty" / "mrc_table11.dta",
50
+ ]
51
+ CHETTY_MRC_TABLE11 = next(
52
+ (path for path in CHETTY_MRC_TABLE11_CANDIDATES if path.exists()),
53
+ CHETTY_MRC_TABLE11_CANDIDATES[0],
54
+ )
55
+ # Chetty OPE-to-super-OPE crosswalk used to attach tier to NSC schools.
56
+
46
57
  INPUT_NSC = PACKAGE_NSC / "input"
47
58
  # Folder for secured Census inputs that are not packaged with the code.
48
59
 
@@ -85,21 +96,31 @@ COLLEGE_TYPES = ["any", "4yr", "2yr", "elite"]
85
96
  college_crosswalk = (
86
97
  pl.read_excel(
87
98
  COLLEGE_CROSSWALK,
88
- columns=["ID_IPEDS", "ID_OPE", "ID_FSC_long", "name"],
99
+ columns=["ID_IPEDS", "ID_OPE", "ID_FSC", "ID_FSC_long", "name"],
89
100
  )
90
101
  .with_columns(
91
- pl.col("ID_FSC_long")
92
- .cast(pl.String)
93
- .str.strip_chars()
94
- .str.replace(r"\.0$", "")
102
+ pl.when(
103
+ pl.col("ID_FSC_long").is_not_null()
104
+ & (pl.col("ID_FSC_long").cast(pl.String).str.strip_chars() != "")
105
+ )
106
+ .then(pl.col("ID_FSC_long").cast(pl.String).str.strip_chars())
107
+ .when(pl.col("ID_FSC").is_not_null())
108
+ .then(
109
+ pl.col("ID_FSC").cast(pl.String).str.strip_chars().str.replace(r"\.0$", "")
110
+ + pl.lit("-00")
111
+ )
112
+ .otherwise(None)
95
113
  .alias("ID_FSC"),
96
114
  pl.col("ID_IPEDS").cast(pl.Int64, strict=False).alias("unitid"),
97
115
  pl.col("ID_OPE").cast(pl.Int64, strict=False),
98
116
  )
99
117
  .select("ID_FSC", "unitid", "ID_OPE", "name")
100
118
  .rename({"name": "college_name_crosswalk"})
101
- .drop_nulls("ID_FSC")
119
+ .drop_nulls(["ID_FSC", "unitid"])
102
120
  .unique("ID_FSC", keep="first")
121
+ .with_columns(
122
+ pl.col("ID_FSC").str.slice(0, 6).cast(pl.Int64, strict=False).alias("opeid")
123
+ )
103
124
  )
104
125
 
105
126
 
@@ -210,24 +231,42 @@ directory = (
210
231
  .select("unitid", "college_name_directory", "years_directory", "ownership_directory")
211
232
  )
212
233
 
213
- # Chetty/Barron tiers are keyed at the super-OPE level. The NSC college
214
- # crosswalk carries OPE IDs, so joining tier onto college_ref makes the tier
215
- # available on each enrollment spell.
234
+ # Chetty/Barron tiers are keyed at super-OPE level. Table 11 maps school OPE IDs
235
+ # to those super-OPE groups, which is the same route Sarah's Stata code uses.
216
236
  chetty_tiers = (
217
237
  scan_readstat(
218
238
  CHETTY_MRC_TABLE2,
219
239
  missing_string_as_null=True,
220
240
  value_labels_as_strings=False,
221
241
  )
222
- .select("super_opeid", "tier")
242
+ .select("super_opeid", "tier", "tier_name")
223
243
  .collect()
224
244
  .with_columns(
225
- pl.col("super_opeid").cast(pl.Int64, strict=False).alias("ID_OPE"),
245
+ pl.col("super_opeid").cast(pl.Int64, strict=False),
226
246
  pl.col("tier").cast(pl.Int8, strict=False),
227
247
  )
228
- .select("ID_OPE", "tier")
229
- .drop_nulls("ID_OPE")
230
- .unique("ID_OPE", keep="first")
248
+ .drop_nulls("super_opeid")
249
+ .unique("super_opeid", keep="first")
250
+ )
251
+
252
+ chetty_ope_crosswalk = (
253
+ scan_readstat(
254
+ CHETTY_MRC_TABLE11,
255
+ missing_string_as_null=True,
256
+ value_labels_as_strings=False,
257
+ )
258
+ .select("opeid", "super_opeid", "superopeid_name")
259
+ .collect()
260
+ .with_columns(
261
+ pl.col("opeid").cast(pl.Int64, strict=False),
262
+ pl.col("super_opeid").cast(pl.Int64, strict=False),
263
+ )
264
+ .drop_nulls("opeid")
265
+ )
266
+
267
+ chetty_by_opeid = (
268
+ chetty_ope_crosswalk.join(chetty_tiers, on="super_opeid", how="left")
269
+ .unique("opeid", keep="first")
231
270
  )
232
271
 
233
272
 
@@ -240,7 +279,7 @@ college_ref = (
240
279
  college_crosswalk.join(ipeds_2013, on="unitid", how="left")
241
280
  .join(ipeds_manual, on="unitid", how="left")
242
281
  .join(directory, on="unitid", how="left")
243
- .join(chetty_tiers, on="ID_OPE", how="left", validate="m:1")
282
+ .join(chetty_by_opeid, on="opeid", how="left", validate="m:1")
244
283
  .with_columns(
245
284
  pl.coalesce(
246
285
  [
@@ -279,6 +318,8 @@ college_ref = (
279
318
  "ID_FSC",
280
319
  "unitid",
281
320
  "ID_OPE",
321
+ "opeid",
322
+ "super_opeid",
282
323
  "college_name",
283
324
  "college_years",
284
325
  "college_ownership",
@@ -286,6 +327,8 @@ college_ref = (
286
327
  "college_4yr",
287
328
  "college_2yr",
288
329
  "tier",
330
+ "tier_name",
331
+ "superopeid_name",
289
332
  "college_elite",
290
333
  )
291
334
  )
@@ -415,12 +458,12 @@ nsc_new = (
415
458
  .with_row_index("origsrt", offset=1)
416
459
  .filter(pl.col("studyid").is_not_null())
417
460
  .with_columns(
418
- pl.col("studyid").cast(pl.String).str.replace_all("_", "").alias("sid_cepr")
461
+ pl.col("studyid").cast(pl.String).str.split("_").alias("sid_cepr")
419
462
  )
420
463
  .explode("sid_cepr")
421
464
  .filter(pl.col("sid_cepr") != "")
422
465
  .with_columns(
423
- pl.col("sid_cepr").cast(pl.String).str.replace_all("_", "").cast(pl.Int64, strict=False)
466
+ pl.col("sid_cepr").cast(pl.Int64, strict=False)
424
467
  )
425
468
  .filter(
426
469
  pl.col("sid_cepr").is_not_null()
@@ -759,8 +802,15 @@ for year in range(1, N_YEARS_OUT + 1):
759
802
  end_month, end_day = 6, 30
760
803
 
761
804
  bounded = enroll.with_columns(
762
- pl.date(start_year, start_month, start_day).alias("_window_start"),
763
- pl.date(end_year, end_month, end_day).alias("_window_end"),
805
+ start_year.alias("_window_start_year"),
806
+ end_year.alias("_window_end_year"),
807
+ ).with_columns(
808
+ pl.date(pl.col("_window_start_year"), start_month, start_day).alias(
809
+ "_window_start"
810
+ ),
811
+ pl.date(pl.col("_window_end_year"), end_month, end_day).alias(
812
+ "_window_end"
813
+ ),
764
814
  ).with_columns(
765
815
  (
766
816
  (pl.col("term_start_date") <= pl.col("_window_end"))
@@ -1211,9 +1261,15 @@ nsc_outcomes = (
1211
1261
  )
1212
1262
 
1213
1263
  for year in range(1, N_YEARS_OUT + 1):
1214
- in_start = pl.date(pl.col("cohort_18") + year - 1, 7, 1)
1215
- by_start = pl.date(pl.col("cohort_18"), 7, 1)
1216
- by_end = pl.date(pl.col("cohort_18") + year, 6, 30)
1264
+ nsc_outcomes = nsc_outcomes.with_columns(
1265
+ (pl.col("cohort_18") + year - 1).alias("_in_start_year"),
1266
+ pl.col("cohort_18").alias("_by_start_year"),
1267
+ (pl.col("cohort_18") + year).alias("_by_end_year"),
1268
+ ).with_columns(
1269
+ pl.date(pl.col("_in_start_year"), 7, 1).alias("_in_start"),
1270
+ pl.date(pl.col("_by_start_year"), 7, 1).alias("_by_start"),
1271
+ pl.date(pl.col("_by_end_year"), 6, 30).alias("_by_end"),
1272
+ )
1217
1273
 
1218
1274
  att_in_columns = [
1219
1275
  column
@@ -1235,7 +1291,7 @@ for year in range(1, N_YEARS_OUT + 1):
1235
1291
 
1236
1292
  nsc_outcomes = nsc_outcomes.with_columns(
1237
1293
  [
1238
- pl.when(in_start > NSC_CUTOFF_DATE)
1294
+ pl.when(pl.col("_in_start") > NSC_CUTOFF_DATE)
1239
1295
  .then(None)
1240
1296
  .when(pl.col(column).is_null())
1241
1297
  .then(0)
@@ -1246,7 +1302,7 @@ for year in range(1, N_YEARS_OUT + 1):
1246
1302
  ]
1247
1303
  +
1248
1304
  [
1249
- pl.when(by_start > NSC_CUTOFF_DATE)
1305
+ pl.when(pl.col("_by_start") > NSC_CUTOFF_DATE)
1250
1306
  .then(None)
1251
1307
  .when(pl.col(column).is_null())
1252
1308
  .then(0)
@@ -1257,7 +1313,7 @@ for year in range(1, N_YEARS_OUT + 1):
1257
1313
  ]
1258
1314
  +
1259
1315
  [
1260
- pl.when(by_end > NSC_CUTOFF_DATE)
1316
+ pl.when(pl.col("_by_end") > NSC_CUTOFF_DATE)
1261
1317
  .then(None)
1262
1318
  .when(pl.col(column).is_null())
1263
1319
  .then(0)
File without changes