ltc-code 0.2.24__tar.gz → 0.2.25__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.
- {ltc_code-0.2.24 → ltc_code-0.2.25}/PKG-INFO +1 -1
- {ltc_code-0.2.24 → ltc_code-0.2.25}/pyproject.toml +1 -1
- {ltc_code-0.2.24 → ltc_code-0.2.25}/pyproject.toml.orig +1 -1
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/build_nsc_outcomes.py +317 -202
- ltc_code-0.2.25/src/ltc_code/nsc/dhs_stem/dhs_stem_cip_additions_2024.csv +252 -0
- ltc_code-0.2.25/src/ltc_code/nsc/dhs_stem/extract_dhs_stem_cips.R +50 -0
- ltc_code-0.2.25/src/ltc_code/nsc/dhs_stem/stemList2024.pdf +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/README.md +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/aspire.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/check_cmo_apps.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/christel_house.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/democracy_prep.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/green_dot.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/helpers.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/ilt.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/kipp_nj.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/main.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/mappings.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/rocketship.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/yes_prep.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/aspire.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/christel_house.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/democracy_prep.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/green_dot.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/ilt.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/kipp.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/kipp_nj.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/rocketship.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/yes_prep.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/BALANCE.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/FS.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/ITT.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/TOT.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/apps_helpers.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/harmony.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260706_ceprscripts/main.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260712_uncommon_scripts/main.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260712_uncommon_scripts/mappings.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260712_uncommon_scripts/uncommon.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/__init__.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/aspire.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/check_cmo_apps.do +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/christel_house.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/green_dot.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/helpers.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/june13.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/june2.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/june30.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/june5.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/june7.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/kipp_nj.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/kipp_tx.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/main.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/make_summary_stats_table.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/mappings.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/may27.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/__init__.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/input/.gitkeep +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/naics.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/output/.gitkeep +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/raw/ipeds_data.dta +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/nsc/run_nsc_outcomes.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/polars_dates.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/rocketship.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/schema_mapping.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/school_name_xwalk/__init__.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/school_name_xwalk/all_schools_with_ccd.csv +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/school_name_xwalk/merge_school_ccd.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/signal_var_calcs.py +0 -0
- {ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/yes_prep.py +0 -0
|
@@ -76,6 +76,12 @@ OUTCOMES = OUTPUT_NSC / "nsc_outcomes.parquet"
|
|
|
76
76
|
# Final student-level NSC outcomes file.
|
|
77
77
|
|
|
78
78
|
|
|
79
|
+
DHS_STEM_CIP_ADDITIONS_FILE = (
|
|
80
|
+
PACKAGE_NSC / "dhs_stem" / "dhs_stem_cip_additions_2024.csv"
|
|
81
|
+
)
|
|
82
|
+
# Exact six-digit additions in the fixed July 22, 2024 DHS STEM list.
|
|
83
|
+
|
|
84
|
+
|
|
79
85
|
###########################################################
|
|
80
86
|
# Define run settings
|
|
81
87
|
###########################################################
|
|
@@ -84,11 +90,128 @@ N_YEARS_OUT = 8
|
|
|
84
90
|
NSC_OBSERVATION_YEAR = 2026
|
|
85
91
|
NSC_CUTOFF_DATE = date(2026, 12, 31)
|
|
86
92
|
RANDOM_SEED = 3852804
|
|
87
|
-
|
|
93
|
+
SARAH_STEM_CIP_FAMILIES = {"11", "14", "15", "26", "27", "40", "41"}
|
|
94
|
+
DHS_STEM_CIP_FAMILIES = {"14", "26", "27", "40"}
|
|
95
|
+
STEM_DEFINITIONS = ["sarah", "dhs"]
|
|
88
96
|
COLLEGE_TYPES = ["any", "4yr", "2yr", "elite"]
|
|
89
97
|
AGE_ATTENDANCE_TYPES = ["any", "4yr", "2yr"]
|
|
90
98
|
AGE_ATTENDANCE_RANGE = range(18, 27)
|
|
91
99
|
|
|
100
|
+
# These ordered rules exactly reproduce Sarah's Stata replacements. Every rule
|
|
101
|
+
# checks the original CIP slot, so the last matching rule wins when names overlap.
|
|
102
|
+
MAJOR_TO_CIP_RULES = [
|
|
103
|
+
("ECONOMICS", "4506"),
|
|
104
|
+
("BUSINESS|FINANCE", "52"),
|
|
105
|
+
("OPERATIONS MANAG", "52"),
|
|
106
|
+
("MARKETING", "5214"),
|
|
107
|
+
("MANAGEMENT", "5213"),
|
|
108
|
+
("ANTHRO|ARCHEO|CRIMINO|DEMOGRA|POLITIC|SOCIOLO|HUMANI|GOVERN|GEOGRA", "45"),
|
|
109
|
+
("VISUAL|PERFORM|ART|DANCE|PHOTO|FILM|MUSIC|MEDIA|ENTERTAIN|DRAMA|CRAFT|THEATRE|THEATER", "50"),
|
|
110
|
+
("HISTORY", "54"),
|
|
111
|
+
("PSYCHOLOGY", "42"),
|
|
112
|
+
("PHILOSO", "38"),
|
|
113
|
+
("LIBERAL|GENERAL STUDIES", "24"),
|
|
114
|
+
("ENGLISH|ENGLISH LANGUAGE", "23"),
|
|
115
|
+
("ENGLISH LIERATURE|WRITING", "23"),
|
|
116
|
+
("LEGAL|LAW", "22"),
|
|
117
|
+
("FOREIGN LANGUAGE|LANGUAGES|SPAN|JAPAN|CHIN|COMPARATIVE LING|FRENCH", "16"),
|
|
118
|
+
("EDUCATION", "13"),
|
|
119
|
+
("COMMUNI", "09"),
|
|
120
|
+
("ETHNIC|CULTURAL|GENDER|WOMEN", "05"),
|
|
121
|
+
("ENGI", "14"),
|
|
122
|
+
("COMPUT|INFORMATION TECH", "11"),
|
|
123
|
+
("EDUC|CURRIC|EARLY CHI", "13"),
|
|
124
|
+
("SCHOOL COUN|STUDENT COUN", "13"),
|
|
125
|
+
("LIBRA", "25"),
|
|
126
|
+
("BIOLOG|NEURO|BIOTECH", "26"),
|
|
127
|
+
("MATH", "27"),
|
|
128
|
+
("LIBRA", "25"),
|
|
129
|
+
("RELIG", "38"),
|
|
130
|
+
("THEOLOG", "39"),
|
|
131
|
+
("ASTRON|ATMOS|GEOLOG|CHEMI|PHYSIC|METEO", "40"),
|
|
132
|
+
("PUBLIC ADMIN|PUBLIC POL|SOCIAL WORK|COMMUNITY ORG|SOCIAL SERVICE|HUMAN SERV", "44"),
|
|
133
|
+
("BIOCHEM|BIOPHY|PHYSIO|BOTANY|ANATOMY|ZOO|GENETIC|GENOM|PHARMA|TOXICO|ECOLOG|EPIDEM|WILDLIFE", "26"),
|
|
134
|
+
("VETERINARY|DENT|HEALTH SCI", "51"),
|
|
135
|
+
("SPORT MANAGEMENT|SPORTS MANAGEMENT|KINESIO|EXER", "31"),
|
|
136
|
+
("PUBLIC RELA|ADVERTIS|RADIO|TELEV|JOURNA", "09"),
|
|
137
|
+
("PUBLIC HEALTH|REHAB|PHYSICAL THER|PREMED|PRE-MED|PRE-VET|NUR|MEDIC|HEALTH CARE ADM", "51"),
|
|
138
|
+
("PLANT|SOIL|AGRI|TURF|HORTIC|FOOD SCI|ANIMAL", "01"),
|
|
139
|
+
("ARCHI", "04"),
|
|
140
|
+
("DESIGN", "50"),
|
|
141
|
+
("HUMAN RESO|HOSPITALITY|HOTEL", "52"),
|
|
142
|
+
("FOREST|ENVIRONMENTAL STUD|ENVIRONMENTAL SCI", "03"),
|
|
143
|
+
("HUMAN RESO|HOSPITALITY|HOTEL|FASHION MERCH", "52"),
|
|
144
|
+
("FOODS|NUTRITION", "19"),
|
|
145
|
+
("CRIMINAL JUS|CRIME & JUST", "43"),
|
|
146
|
+
("CLASSICS", "16"),
|
|
147
|
+
("ACCOUNTING", "5203"),
|
|
148
|
+
("AUTOMOTIVE TECH|AUTOMOB", "47"),
|
|
149
|
+
("CLINICAL LAB", "51"),
|
|
150
|
+
("HUMAN DEV", "19"),
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
DHS_STEM_CIP_ADDITIONS = set(
|
|
154
|
+
pl.read_csv(
|
|
155
|
+
DHS_STEM_CIP_ADDITIONS_FILE,
|
|
156
|
+
schema_overrides={"cip6": pl.String},
|
|
157
|
+
)["cip6"].to_list()
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if len(DHS_STEM_CIP_ADDITIONS) != 251:
|
|
161
|
+
raise ValueError(
|
|
162
|
+
"Expected 251 exact six-digit additions in the 2024 DHS STEM lookup, "
|
|
163
|
+
f"found {len(DHS_STEM_CIP_ADDITIONS)}"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
|
|
167
|
+
def impute_cip_from_major(cip_column, major_column):
|
|
168
|
+
"""Fill a missing CIP with Sarah's ordered major-name replacement rules."""
|
|
169
|
+
cip = pl.col(cip_column).cast(pl.String).str.strip_chars()
|
|
170
|
+
major = pl.col(major_column).cast(pl.String).str.to_uppercase().fill_null("")
|
|
171
|
+
imputed = pl.lit(None, dtype=pl.String)
|
|
172
|
+
|
|
173
|
+
for pattern, cip_value in MAJOR_TO_CIP_RULES:
|
|
174
|
+
imputed = (
|
|
175
|
+
pl.when(major.str.contains(pattern, literal=False))
|
|
176
|
+
.then(pl.lit(cip_value))
|
|
177
|
+
.otherwise(imputed)
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
return (
|
|
181
|
+
pl.when(cip.is_null() | cip.is_in(["", "."]))
|
|
182
|
+
.then(imputed)
|
|
183
|
+
.otherwise(cip)
|
|
184
|
+
.alias(cip_column)
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def stem_flag_from_cips(cip_columns, definition):
|
|
189
|
+
"""Classify a row as STEM when any of its four imputed CIP slots qualify."""
|
|
190
|
+
cip_digits = [
|
|
191
|
+
pl.col(column)
|
|
192
|
+
.cast(pl.String)
|
|
193
|
+
.str.strip_chars()
|
|
194
|
+
.str.replace(r"\.0$", "")
|
|
195
|
+
.str.replace_all(r"\D", "")
|
|
196
|
+
for column in cip_columns
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
if definition == "sarah":
|
|
200
|
+
conditions = [
|
|
201
|
+
cip.str.slice(0, 2).is_in(SARAH_STEM_CIP_FAMILIES)
|
|
202
|
+
for cip in cip_digits
|
|
203
|
+
]
|
|
204
|
+
elif definition == "dhs":
|
|
205
|
+
conditions = [
|
|
206
|
+
cip.str.slice(0, 2).is_in(DHS_STEM_CIP_FAMILIES)
|
|
207
|
+
| ((cip.str.len_chars() == 6) & cip.is_in(DHS_STEM_CIP_ADDITIONS))
|
|
208
|
+
for cip in cip_digits
|
|
209
|
+
]
|
|
210
|
+
else:
|
|
211
|
+
raise ValueError(f"Unknown STEM definition: {definition}")
|
|
212
|
+
|
|
213
|
+
return pl.any_horizontal(conditions).fill_null(False).cast(pl.Int8)
|
|
214
|
+
|
|
92
215
|
|
|
93
216
|
###########################################################
|
|
94
217
|
# Read college crosswalk
|
|
@@ -621,6 +744,10 @@ nsc_new = (
|
|
|
621
744
|
"Enrollment CIP 1": "enrollmentcip1",
|
|
622
745
|
"Enrollment Major 2": "enrollmentmajor2",
|
|
623
746
|
"Enrollment CIP 2": "enrollmentcip2",
|
|
747
|
+
"Enrollment Major 3": "enrollmentmajor3",
|
|
748
|
+
"Enrollment CIP 3": "enrollmentcip3",
|
|
749
|
+
"Enrollment Major 4": "enrollmentmajor4",
|
|
750
|
+
"Enrollment CIP 4": "enrollmentcip4",
|
|
624
751
|
"Graduated?": "graduated",
|
|
625
752
|
"Graduation Date": "graduationdate",
|
|
626
753
|
"Degree Title": "degreetitle",
|
|
@@ -635,7 +762,7 @@ nsc_new = (
|
|
|
635
762
|
"College Sequence": "collegesequence",
|
|
636
763
|
"Student Age at start of term": "studentageatstartofterm",
|
|
637
764
|
|
|
638
|
-
})
|
|
765
|
+
}, strict=False)
|
|
639
766
|
.with_row_index("origsrt", offset=1)
|
|
640
767
|
.filter(pl.col("studyid").is_not_null())
|
|
641
768
|
.with_columns(
|
|
@@ -689,6 +816,15 @@ nsc = (
|
|
|
689
816
|
pl.concat([nsc_old, nsc_new], how="diagonal_relaxed")
|
|
690
817
|
)
|
|
691
818
|
|
|
819
|
+
# Older NSC extracts may omit some enrollment-major slots entirely. Add those
|
|
820
|
+
# slots as nulls so enrollment and degree majors always retain distinct names.
|
|
821
|
+
for column in [
|
|
822
|
+
*[f"enrollmentcip{index}" for index in range(1, 5)],
|
|
823
|
+
*[f"enrollmentmajor{index}" for index in range(1, 5)],
|
|
824
|
+
]:
|
|
825
|
+
if column not in nsc.columns:
|
|
826
|
+
nsc = nsc.with_columns(pl.lit(None).cast(pl.String).alias(column))
|
|
827
|
+
|
|
692
828
|
required_nsc_columns = [
|
|
693
829
|
"sid_cepr",
|
|
694
830
|
"ID_FSC",
|
|
@@ -708,6 +844,14 @@ required_nsc_columns = [
|
|
|
708
844
|
"degreemajor2",
|
|
709
845
|
"degreemajor3",
|
|
710
846
|
"degreemajor4",
|
|
847
|
+
"enrollmentcip1",
|
|
848
|
+
"enrollmentcip2",
|
|
849
|
+
"enrollmentcip3",
|
|
850
|
+
"enrollmentcip4",
|
|
851
|
+
"enrollmentmajor1",
|
|
852
|
+
"enrollmentmajor2",
|
|
853
|
+
"enrollmentmajor3",
|
|
854
|
+
"enrollmentmajor4",
|
|
711
855
|
"NSCdatayear",
|
|
712
856
|
"searchbeginyear",
|
|
713
857
|
"collegesequence",
|
|
@@ -768,6 +912,32 @@ nsc = (
|
|
|
768
912
|
)
|
|
769
913
|
)
|
|
770
914
|
|
|
915
|
+
# Impute every missing enrollment and degree CIP slot independently from its
|
|
916
|
+
# corresponding major name, using the same ordered rules Sarah uses for degree 1.
|
|
917
|
+
for cip_prefix, major_prefix in [
|
|
918
|
+
("enrollmentcip", "enrollmentmajor"),
|
|
919
|
+
("degreecip", "degreemajor"),
|
|
920
|
+
]:
|
|
921
|
+
nsc = nsc.with_columns(
|
|
922
|
+
[
|
|
923
|
+
impute_cip_from_major(
|
|
924
|
+
f"{cip_prefix}{index}",
|
|
925
|
+
f"{major_prefix}{index}",
|
|
926
|
+
)
|
|
927
|
+
for index in range(1, 5)
|
|
928
|
+
]
|
|
929
|
+
)
|
|
930
|
+
|
|
931
|
+
# A row is STEM when any of its four imputed enrollment-major CIPs qualify.
|
|
932
|
+
enrollment_cip_columns = [f"enrollmentcip{index}" for index in range(1, 5)]
|
|
933
|
+
nsc = nsc.with_columns(
|
|
934
|
+
[
|
|
935
|
+
stem_flag_from_cips(enrollment_cip_columns, definition)
|
|
936
|
+
.alias(f"_enrollment_stem_{definition}")
|
|
937
|
+
for definition in STEM_DEFINITIONS
|
|
938
|
+
]
|
|
939
|
+
)
|
|
940
|
+
|
|
771
941
|
|
|
772
942
|
###########################################################
|
|
773
943
|
# Build enrollment outcomes
|
|
@@ -895,6 +1065,8 @@ enroll_weeks = (
|
|
|
895
1065
|
"week_end",
|
|
896
1066
|
"_term_att",
|
|
897
1067
|
"_enrollment_score",
|
|
1068
|
+
"_enrollment_stem_sarah",
|
|
1069
|
+
"_enrollment_stem_dhs",
|
|
898
1070
|
"NSCdatayear",
|
|
899
1071
|
"searchbeginyear",
|
|
900
1072
|
"collegesequence",
|
|
@@ -925,6 +1097,14 @@ enroll_weeks = (
|
|
|
925
1097
|
(pl.col("week") != pl.col("week").shift(1) + 1)
|
|
926
1098
|
| (pl.col("sid_cepr") != pl.col("sid_cepr").shift(1))
|
|
927
1099
|
| (pl.col("ID_FSC") != pl.col("ID_FSC").shift(1))
|
|
1100
|
+
| (
|
|
1101
|
+
pl.col("_enrollment_stem_sarah")
|
|
1102
|
+
!= pl.col("_enrollment_stem_sarah").shift(1)
|
|
1103
|
+
)
|
|
1104
|
+
| (
|
|
1105
|
+
pl.col("_enrollment_stem_dhs")
|
|
1106
|
+
!= pl.col("_enrollment_stem_dhs").shift(1)
|
|
1107
|
+
)
|
|
928
1108
|
)
|
|
929
1109
|
.fill_null(True)
|
|
930
1110
|
.cast(pl.Int64)
|
|
@@ -949,6 +1129,8 @@ enroll = (
|
|
|
949
1129
|
pl.col("k_mean").drop_nulls().first(),
|
|
950
1130
|
pl.col("completion_rate_150pct_ip").drop_nulls().first(),
|
|
951
1131
|
pl.col("_term_att").max(),
|
|
1132
|
+
pl.col("_enrollment_stem_sarah").max(),
|
|
1133
|
+
pl.col("_enrollment_stem_dhs").max(),
|
|
952
1134
|
pl.col("week").min().alias("week_start"),
|
|
953
1135
|
pl.col("week").max().alias("week_end"),
|
|
954
1136
|
pl.col("_enrollment_score").max(),
|
|
@@ -1019,6 +1201,32 @@ for year in range(1, N_YEARS_OUT + 1):
|
|
|
1019
1201
|
.alias(f"att_{college_type}_{label}")
|
|
1020
1202
|
for college_type in COLLEGE_TYPES
|
|
1021
1203
|
]
|
|
1204
|
+
+ [
|
|
1205
|
+
expression
|
|
1206
|
+
for definition in STEM_DEFINITIONS
|
|
1207
|
+
for expression in [
|
|
1208
|
+
(
|
|
1209
|
+
pl.col("_overlaps")
|
|
1210
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1211
|
+
)
|
|
1212
|
+
.max()
|
|
1213
|
+
.alias(f"att_stem_{definition}_{label}"),
|
|
1214
|
+
(
|
|
1215
|
+
pl.col("_overlaps")
|
|
1216
|
+
* pl.col("college_4yr").fill_null(0).cast(pl.Int8)
|
|
1217
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1218
|
+
)
|
|
1219
|
+
.max()
|
|
1220
|
+
.alias(f"att_4yr_stem_{definition}_{label}"),
|
|
1221
|
+
(
|
|
1222
|
+
pl.col("_overlaps")
|
|
1223
|
+
* pl.col("college_2yr").fill_null(0).cast(pl.Int8)
|
|
1224
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1225
|
+
)
|
|
1226
|
+
.max()
|
|
1227
|
+
.alias(f"att_2yr_stem_{definition}_{label}"),
|
|
1228
|
+
]
|
|
1229
|
+
]
|
|
1022
1230
|
)
|
|
1023
1231
|
)
|
|
1024
1232
|
|
|
@@ -1053,6 +1261,32 @@ for age in AGE_ATTENDANCE_RANGE:
|
|
|
1053
1261
|
.alias(f"att_{college_type}_{age}")
|
|
1054
1262
|
for college_type in AGE_ATTENDANCE_TYPES
|
|
1055
1263
|
]
|
|
1264
|
+
+ [
|
|
1265
|
+
expression
|
|
1266
|
+
for definition in STEM_DEFINITIONS
|
|
1267
|
+
for expression in [
|
|
1268
|
+
(
|
|
1269
|
+
pl.col("_overlaps")
|
|
1270
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1271
|
+
)
|
|
1272
|
+
.max()
|
|
1273
|
+
.alias(f"att_stem_{definition}_{age}"),
|
|
1274
|
+
(
|
|
1275
|
+
pl.col("_overlaps")
|
|
1276
|
+
* pl.col("college_4yr").fill_null(0).cast(pl.Int8)
|
|
1277
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1278
|
+
)
|
|
1279
|
+
.max()
|
|
1280
|
+
.alias(f"att_4yr_stem_{definition}_{age}"),
|
|
1281
|
+
(
|
|
1282
|
+
pl.col("_overlaps")
|
|
1283
|
+
* pl.col("college_2yr").fill_null(0).cast(pl.Int8)
|
|
1284
|
+
* pl.col(f"_enrollment_stem_{definition}")
|
|
1285
|
+
)
|
|
1286
|
+
.max()
|
|
1287
|
+
.alias(f"att_2yr_stem_{definition}_{age}"),
|
|
1288
|
+
]
|
|
1289
|
+
]
|
|
1056
1290
|
)
|
|
1057
1291
|
)
|
|
1058
1292
|
|
|
@@ -1065,7 +1299,17 @@ for piece in enrollment_pieces[1:]:
|
|
|
1065
1299
|
# Sarah makes these categories disjoint: a 4-year enrollment wins over 2-year.
|
|
1066
1300
|
for column in enrollment_outcomes.columns:
|
|
1067
1301
|
if column.startswith("att_2yr_"):
|
|
1068
|
-
|
|
1302
|
+
if "_stem_" in column:
|
|
1303
|
+
definition = next(
|
|
1304
|
+
item for item in STEM_DEFINITIONS if f"_stem_{item}_" in column
|
|
1305
|
+
)
|
|
1306
|
+
four_year_column = column.replace(
|
|
1307
|
+
f"att_2yr_stem_{definition}_",
|
|
1308
|
+
"att_4yr_",
|
|
1309
|
+
)
|
|
1310
|
+
else:
|
|
1311
|
+
four_year_column = column.replace("att_2yr_", "att_4yr_")
|
|
1312
|
+
|
|
1069
1313
|
enrollment_outcomes = enrollment_outcomes.with_columns(
|
|
1070
1314
|
pl.when(pl.col(four_year_column) == 1)
|
|
1071
1315
|
.then(0)
|
|
@@ -1211,211 +1455,21 @@ degrees = (
|
|
|
1211
1455
|
.otherwise(pl.col("_degree"))
|
|
1212
1456
|
.alias("_degree")
|
|
1213
1457
|
)
|
|
1214
|
-
.with_columns(
|
|
1215
|
-
pl.col("degreemajor1").cast(pl.String).str.to_uppercase().alias("_major1_upper"),
|
|
1216
|
-
pl.col("degreecip1").cast(pl.String).str.strip_chars().alias("_degreecip1_clean"),
|
|
1217
|
-
)
|
|
1218
|
-
.with_columns(
|
|
1219
|
-
pl.when(
|
|
1220
|
-
pl.col("_degreecip1_clean").is_null()
|
|
1221
|
-
| (pl.col("_degreecip1_clean") == "")
|
|
1222
|
-
| (pl.col("_degreecip1_clean") == ".")
|
|
1223
|
-
)
|
|
1224
|
-
.then(
|
|
1225
|
-
pl.when(pl.col("_major1_upper").str.contains("ECONOMICS", literal=False))
|
|
1226
|
-
.then(pl.lit("4506"))
|
|
1227
|
-
.when(
|
|
1228
|
-
pl.col("_major1_upper").str.contains(
|
|
1229
|
-
"BUSINESS|FINANCE|OPERATIONS MANAG", literal=False
|
|
1230
|
-
)
|
|
1231
|
-
)
|
|
1232
|
-
.then(pl.lit("52"))
|
|
1233
|
-
.when(pl.col("_major1_upper").str.contains("MARKETING", literal=False))
|
|
1234
|
-
.then(pl.lit("5214"))
|
|
1235
|
-
.when(pl.col("_major1_upper").str.contains("MANAGEMENT", literal=False))
|
|
1236
|
-
.then(pl.lit("5213"))
|
|
1237
|
-
.when(
|
|
1238
|
-
pl.col("_major1_upper").str.contains(
|
|
1239
|
-
"ANTHRO|ARCHEO|CRIMINO|DEMOGRA|POLITIC|SOCIOLO|HUMANI|GOVERN|GEOGRA",
|
|
1240
|
-
literal=False,
|
|
1241
|
-
)
|
|
1242
|
-
)
|
|
1243
|
-
.then(pl.lit("45"))
|
|
1244
|
-
.when(
|
|
1245
|
-
pl.col("_major1_upper").str.contains(
|
|
1246
|
-
"VISUAL|PERFORM|ART|DANCE|PHOTO|FILM|MUSIC|MEDIA|ENTERTAIN|DRAMA|CRAFT|THEATRE|THEATER|DESIGN",
|
|
1247
|
-
literal=False,
|
|
1248
|
-
)
|
|
1249
|
-
)
|
|
1250
|
-
.then(pl.lit("50"))
|
|
1251
|
-
.when(pl.col("_major1_upper").str.contains("HISTORY", literal=False))
|
|
1252
|
-
.then(pl.lit("54"))
|
|
1253
|
-
.when(pl.col("_major1_upper").str.contains("PSYCHOLOGY", literal=False))
|
|
1254
|
-
.then(pl.lit("42"))
|
|
1255
|
-
.when(pl.col("_major1_upper").str.contains("PHILOSO|RELIG", literal=False))
|
|
1256
|
-
.then(pl.lit("38"))
|
|
1257
|
-
.when(
|
|
1258
|
-
pl.col("_major1_upper").str.contains(
|
|
1259
|
-
"LIBERAL|GENERAL STUDIES", literal=False
|
|
1260
|
-
)
|
|
1261
|
-
)
|
|
1262
|
-
.then(pl.lit("24"))
|
|
1263
|
-
.when(
|
|
1264
|
-
pl.col("_major1_upper").str.contains(
|
|
1265
|
-
"ENGLISH|ENGLISH LANGUAGE|ENGLISH LIERATURE|WRITING",
|
|
1266
|
-
literal=False,
|
|
1267
|
-
)
|
|
1268
|
-
)
|
|
1269
|
-
.then(pl.lit("23"))
|
|
1270
|
-
.when(pl.col("_major1_upper").str.contains("LEGAL|LAW", literal=False))
|
|
1271
|
-
.then(pl.lit("22"))
|
|
1272
|
-
.when(
|
|
1273
|
-
pl.col("_major1_upper").str.contains(
|
|
1274
|
-
"FOREIGN LANGUAGE|LANGUAGES|SPAN|JAPAN|CHIN|COMPARATIVE LING|FRENCH|CLASSICS",
|
|
1275
|
-
literal=False,
|
|
1276
|
-
)
|
|
1277
|
-
)
|
|
1278
|
-
.then(pl.lit("16"))
|
|
1279
|
-
.when(
|
|
1280
|
-
pl.col("_major1_upper").str.contains(
|
|
1281
|
-
"EDUCATION|EDUC|CURRIC|EARLY CHI|SCHOOL COUN|STUDENT COUN",
|
|
1282
|
-
literal=False,
|
|
1283
|
-
)
|
|
1284
|
-
)
|
|
1285
|
-
.then(pl.lit("13"))
|
|
1286
|
-
.when(
|
|
1287
|
-
pl.col("_major1_upper").str.contains(
|
|
1288
|
-
"COMMUNI|PUBLIC RELA|ADVERTIS|RADIO|TELEV|JOURNA",
|
|
1289
|
-
literal=False,
|
|
1290
|
-
)
|
|
1291
|
-
)
|
|
1292
|
-
.then(pl.lit("09"))
|
|
1293
|
-
.when(
|
|
1294
|
-
pl.col("_major1_upper").str.contains(
|
|
1295
|
-
"ETHNIC|CULTURAL|GENDER|WOMEN", literal=False
|
|
1296
|
-
)
|
|
1297
|
-
)
|
|
1298
|
-
.then(pl.lit("05"))
|
|
1299
|
-
.when(pl.col("_major1_upper").str.contains("ENGI", literal=False))
|
|
1300
|
-
.then(pl.lit("14"))
|
|
1301
|
-
.when(
|
|
1302
|
-
pl.col("_major1_upper").str.contains(
|
|
1303
|
-
"COMPUT|INFORMATION TECH", literal=False
|
|
1304
|
-
)
|
|
1305
|
-
)
|
|
1306
|
-
.then(pl.lit("11"))
|
|
1307
|
-
.when(pl.col("_major1_upper").str.contains("LIBRA", literal=False))
|
|
1308
|
-
.then(pl.lit("25"))
|
|
1309
|
-
.when(
|
|
1310
|
-
pl.col("_major1_upper").str.contains(
|
|
1311
|
-
"BIOLOG|NEURO|BIOTECH|BIOCHEM|BIOPHY|PHYSIO|BOTANY|ANATOMY|ZOO|GENETIC|GENOM|PHARMA|TOXICO|ECOLOG|EPIDEM|WILDLIFE",
|
|
1312
|
-
literal=False,
|
|
1313
|
-
)
|
|
1314
|
-
)
|
|
1315
|
-
.then(pl.lit("26"))
|
|
1316
|
-
.when(pl.col("_major1_upper").str.contains("MATH", literal=False))
|
|
1317
|
-
.then(pl.lit("27"))
|
|
1318
|
-
.when(pl.col("_major1_upper").str.contains("THEOLOG", literal=False))
|
|
1319
|
-
.then(pl.lit("39"))
|
|
1320
|
-
.when(
|
|
1321
|
-
pl.col("_major1_upper").str.contains(
|
|
1322
|
-
"ASTRON|ATMOS|GEOLOG|CHEMI|PHYSIC|METEO", literal=False
|
|
1323
|
-
)
|
|
1324
|
-
)
|
|
1325
|
-
.then(pl.lit("40"))
|
|
1326
|
-
.when(
|
|
1327
|
-
pl.col("_major1_upper").str.contains(
|
|
1328
|
-
"PUBLIC ADMIN|PUBLIC POL|SOCIAL WORK|COMMUNITY ORG|SOCIAL SERVICE|HUMAN SERV",
|
|
1329
|
-
literal=False,
|
|
1330
|
-
)
|
|
1331
|
-
)
|
|
1332
|
-
.then(pl.lit("44"))
|
|
1333
|
-
.when(
|
|
1334
|
-
pl.col("_major1_upper").str.contains(
|
|
1335
|
-
"VETERINARY|DENT|HEALTH SCI|PUBLIC HEALTH|REHAB|PHYSICAL THER|PREMED|PRE-MED|PRE-VET|NUR|MEDIC|HEALTH CARE ADM|CLINICAL LAB",
|
|
1336
|
-
literal=False,
|
|
1337
|
-
)
|
|
1338
|
-
)
|
|
1339
|
-
.then(pl.lit("51"))
|
|
1340
|
-
.when(
|
|
1341
|
-
pl.col("_major1_upper").str.contains(
|
|
1342
|
-
"SPORT MANAGEMENT|SPORTS MANAGEMENT|KINESIO|EXER", literal=False
|
|
1343
|
-
)
|
|
1344
|
-
)
|
|
1345
|
-
.then(pl.lit("31"))
|
|
1346
|
-
.when(
|
|
1347
|
-
pl.col("_major1_upper").str.contains(
|
|
1348
|
-
"PLANT|SOIL|AGRI|TURF|HORTIC|FOOD SCI|ANIMAL", literal=False
|
|
1349
|
-
)
|
|
1350
|
-
)
|
|
1351
|
-
.then(pl.lit("01"))
|
|
1352
|
-
.when(pl.col("_major1_upper").str.contains("ARCHI", literal=False))
|
|
1353
|
-
.then(pl.lit("04"))
|
|
1354
|
-
.when(
|
|
1355
|
-
pl.col("_major1_upper").str.contains(
|
|
1356
|
-
"HUMAN RESO|HOSPITALITY|HOTEL|FASHION MERCH", literal=False
|
|
1357
|
-
)
|
|
1358
|
-
)
|
|
1359
|
-
.then(pl.lit("52"))
|
|
1360
|
-
.when(
|
|
1361
|
-
pl.col("_major1_upper").str.contains(
|
|
1362
|
-
"FOREST|ENVIRONMENTAL STUD|ENVIRONMENTAL SCI", literal=False
|
|
1363
|
-
)
|
|
1364
|
-
)
|
|
1365
|
-
.then(pl.lit("03"))
|
|
1366
|
-
.when(
|
|
1367
|
-
pl.col("_major1_upper").str.contains("FOODS|NUTRITION|HUMAN DEV", literal=False)
|
|
1368
|
-
)
|
|
1369
|
-
.then(pl.lit("19"))
|
|
1370
|
-
.when(
|
|
1371
|
-
pl.col("_major1_upper").str.contains(
|
|
1372
|
-
"CRIMINAL JUS|CRIME & JUST", literal=False
|
|
1373
|
-
)
|
|
1374
|
-
)
|
|
1375
|
-
.then(pl.lit("43"))
|
|
1376
|
-
.when(pl.col("_major1_upper").str.contains("ACCOUNTING", literal=False))
|
|
1377
|
-
.then(pl.lit("5203"))
|
|
1378
|
-
.when(
|
|
1379
|
-
pl.col("_major1_upper").str.contains(
|
|
1380
|
-
"AUTOMOTIVE TECH|AUTOMOB", literal=False
|
|
1381
|
-
)
|
|
1382
|
-
)
|
|
1383
|
-
.then(pl.lit("47"))
|
|
1384
|
-
.otherwise(pl.col("_degreecip1_clean"))
|
|
1385
|
-
)
|
|
1386
|
-
.otherwise(pl.col("_degreecip1_clean"))
|
|
1387
|
-
.alias("degreecip1_imputed")
|
|
1388
|
-
)
|
|
1389
1458
|
.with_columns(
|
|
1390
1459
|
[
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
.
|
|
1395
|
-
|
|
1396
|
-
.str.slice(0, 2)
|
|
1397
|
-
.cast(pl.Int64, strict=False)
|
|
1398
|
-
.alias(f"_cip_family{i}")
|
|
1399
|
-
for i in range(1, 5)
|
|
1460
|
+
stem_flag_from_cips(
|
|
1461
|
+
[f"degreecip{index}" for index in range(1, 5)],
|
|
1462
|
+
definition,
|
|
1463
|
+
).alias(f"degree_stem_{definition}")
|
|
1464
|
+
for definition in STEM_DEFINITIONS
|
|
1400
1465
|
]
|
|
1401
1466
|
)
|
|
1402
1467
|
.with_columns(
|
|
1403
|
-
pl.any_horizontal(
|
|
1404
|
-
[pl.col(f"_cip_family{i}").is_in(STEM_CIP_FAMILIES) for i in range(1, 5)]
|
|
1405
|
-
)
|
|
1406
|
-
.fill_null(False)
|
|
1407
|
-
.cast(pl.Int8)
|
|
1408
|
-
.alias("degree_stem"),
|
|
1409
1468
|
pl.coalesce(
|
|
1410
|
-
[pl.col("
|
|
1411
|
-
+ [pl.col(f"degreecip{i}") for i in range(2, 5)]
|
|
1469
|
+
[pl.col(f"degreecip{index}") for index in range(1, 5)]
|
|
1412
1470
|
).alias("degreecip"),
|
|
1413
1471
|
pl.coalesce(
|
|
1414
|
-
[
|
|
1415
|
-
pl.col(column)
|
|
1416
|
-
for column in nsc.columns
|
|
1417
|
-
if column.startswith("degreemajor")
|
|
1418
|
-
]
|
|
1472
|
+
[pl.col(f"degreemajor{index}") for index in range(1, 5)]
|
|
1419
1473
|
).alias("degreemajor"),
|
|
1420
1474
|
)
|
|
1421
1475
|
)
|
|
@@ -1452,6 +1506,33 @@ for year in range(1, N_YEARS_OUT + 1):
|
|
|
1452
1506
|
)
|
|
1453
1507
|
.max()
|
|
1454
1508
|
.alias(f"cmp_elite_byY{year}"),
|
|
1509
|
+
*[
|
|
1510
|
+
expression
|
|
1511
|
+
for definition in STEM_DEFINITIONS
|
|
1512
|
+
for expression in [
|
|
1513
|
+
(
|
|
1514
|
+
pl.col("_by_end")
|
|
1515
|
+
* pl.col("_degree").is_in(["AA", "BA"]).cast(pl.Int8)
|
|
1516
|
+
* pl.col(f"degree_stem_{definition}")
|
|
1517
|
+
)
|
|
1518
|
+
.max()
|
|
1519
|
+
.alias(f"cmp_stem_{definition}_byY{year}"),
|
|
1520
|
+
(
|
|
1521
|
+
pl.col("_by_end")
|
|
1522
|
+
* (pl.col("_degree") == "AA").cast(pl.Int8)
|
|
1523
|
+
* pl.col(f"degree_stem_{definition}")
|
|
1524
|
+
)
|
|
1525
|
+
.max()
|
|
1526
|
+
.alias(f"cmp_AA_stem_{definition}_byY{year}"),
|
|
1527
|
+
(
|
|
1528
|
+
pl.col("_by_end")
|
|
1529
|
+
* (pl.col("_degree") == "BA").cast(pl.Int8)
|
|
1530
|
+
* pl.col(f"degree_stem_{definition}")
|
|
1531
|
+
)
|
|
1532
|
+
.max()
|
|
1533
|
+
.alias(f"cmp_BA_stem_{definition}_byY{year}"),
|
|
1534
|
+
]
|
|
1535
|
+
],
|
|
1455
1536
|
)
|
|
1456
1537
|
)
|
|
1457
1538
|
|
|
@@ -1494,7 +1575,8 @@ degree_details = (
|
|
|
1494
1575
|
pl.col("graduated_date").first().alias("degree_date"),
|
|
1495
1576
|
pl.col("degreecip").first().alias("degreecip"),
|
|
1496
1577
|
pl.col("degreemajor").first().alias("degreemajor"),
|
|
1497
|
-
pl.col("
|
|
1578
|
+
pl.col("degree_stem_sarah").max().alias("degree_stem_sarah"),
|
|
1579
|
+
pl.col("degree_stem_dhs").max().alias("degree_stem_dhs"),
|
|
1498
1580
|
pl.col("ID_FSC").first().alias("ID_FSC_degree"),
|
|
1499
1581
|
pl.col("college_name").first().alias("college_name_degree"),
|
|
1500
1582
|
pl.col("college_years").first().alias("college_years_degree"),
|
|
@@ -1727,6 +1809,39 @@ outcome_columns = [
|
|
|
1727
1809
|
"cmp_elite_byY4", "cmp_elite_byY5", "cmp_elite_byY6", "cmp_elite_byY7", "cmp_elite_byY8",
|
|
1728
1810
|
]
|
|
1729
1811
|
|
|
1812
|
+
stem_outcome_columns = []
|
|
1813
|
+
for year in range(1, N_YEARS_OUT + 1):
|
|
1814
|
+
for prefix in ["in", "by"]:
|
|
1815
|
+
for term in ["", "fall", "spring"]:
|
|
1816
|
+
label = f"{prefix}Y{year}{term}"
|
|
1817
|
+
for definition in STEM_DEFINITIONS:
|
|
1818
|
+
stem_outcome_columns.extend(
|
|
1819
|
+
[
|
|
1820
|
+
f"att_stem_{definition}_{label}",
|
|
1821
|
+
f"att_4yr_stem_{definition}_{label}",
|
|
1822
|
+
f"att_2yr_stem_{definition}_{label}",
|
|
1823
|
+
]
|
|
1824
|
+
)
|
|
1825
|
+
|
|
1826
|
+
for definition in STEM_DEFINITIONS:
|
|
1827
|
+
stem_outcome_columns.extend(
|
|
1828
|
+
[
|
|
1829
|
+
f"cmp_stem_{definition}_byY{year}",
|
|
1830
|
+
f"cmp_AA_stem_{definition}_byY{year}",
|
|
1831
|
+
f"cmp_BA_stem_{definition}_byY{year}",
|
|
1832
|
+
]
|
|
1833
|
+
)
|
|
1834
|
+
|
|
1835
|
+
for age in AGE_ATTENDANCE_RANGE:
|
|
1836
|
+
for definition in STEM_DEFINITIONS:
|
|
1837
|
+
stem_outcome_columns.extend(
|
|
1838
|
+
[
|
|
1839
|
+
f"att_stem_{definition}_{age}",
|
|
1840
|
+
f"att_4yr_stem_{definition}_{age}",
|
|
1841
|
+
f"att_2yr_stem_{definition}_{age}",
|
|
1842
|
+
]
|
|
1843
|
+
)
|
|
1844
|
+
|
|
1730
1845
|
nsc_outcomes = nsc_outcomes.with_columns(
|
|
1731
1846
|
pl.any_horizontal([pl.col(column).fill_null(0) == 1 for column in outcome_columns])
|
|
1732
1847
|
.cast(pl.Int8)
|
|
@@ -1747,7 +1862,7 @@ keep_columns = [
|
|
|
1747
1862
|
"college_name_firstinst",
|
|
1748
1863
|
"tier_firstinst",
|
|
1749
1864
|
"completion_rate_150pct_firstinst",
|
|
1750
|
-
] + outcome_columns
|
|
1865
|
+
] + outcome_columns + stem_outcome_columns
|
|
1751
1866
|
|
|
1752
1867
|
nsc_outcomes_final = nsc_outcomes.select(keep_columns)
|
|
1753
1868
|
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
cip6
|
|
2
|
+
010308
|
|
3
|
+
010901
|
|
4
|
+
010902
|
|
5
|
+
010903
|
|
6
|
+
010904
|
|
7
|
+
010905
|
|
8
|
+
010906
|
|
9
|
+
010907
|
|
10
|
+
010999
|
|
11
|
+
011001
|
|
12
|
+
011002
|
|
13
|
+
011099
|
|
14
|
+
011101
|
|
15
|
+
011102
|
|
16
|
+
011103
|
|
17
|
+
011104
|
|
18
|
+
011105
|
|
19
|
+
011106
|
|
20
|
+
011199
|
|
21
|
+
011201
|
|
22
|
+
011202
|
|
23
|
+
011203
|
|
24
|
+
011299
|
|
25
|
+
018105
|
|
26
|
+
018106
|
|
27
|
+
018107
|
|
28
|
+
018108
|
|
29
|
+
018109
|
|
30
|
+
018110
|
|
31
|
+
018111
|
|
32
|
+
030101
|
|
33
|
+
030103
|
|
34
|
+
030104
|
|
35
|
+
030199
|
|
36
|
+
030204
|
|
37
|
+
030205
|
|
38
|
+
030210
|
|
39
|
+
030501
|
|
40
|
+
030502
|
|
41
|
+
030508
|
|
42
|
+
030509
|
|
43
|
+
030510
|
|
44
|
+
030601
|
|
45
|
+
040601
|
|
46
|
+
040902
|
|
47
|
+
090702
|
|
48
|
+
100304
|
|
49
|
+
110101
|
|
50
|
+
110102
|
|
51
|
+
110103
|
|
52
|
+
110104
|
|
53
|
+
110105
|
|
54
|
+
110199
|
|
55
|
+
110201
|
|
56
|
+
110202
|
|
57
|
+
110203
|
|
58
|
+
110299
|
|
59
|
+
110301
|
|
60
|
+
110401
|
|
61
|
+
110501
|
|
62
|
+
110701
|
|
63
|
+
110801
|
|
64
|
+
110802
|
|
65
|
+
110803
|
|
66
|
+
110804
|
|
67
|
+
110899
|
|
68
|
+
110901
|
|
69
|
+
110902
|
|
70
|
+
111001
|
|
71
|
+
111002
|
|
72
|
+
111003
|
|
73
|
+
111004
|
|
74
|
+
111005
|
|
75
|
+
111006
|
|
76
|
+
111099
|
|
77
|
+
130501
|
|
78
|
+
130601
|
|
79
|
+
130603
|
|
80
|
+
130608
|
|
81
|
+
150000
|
|
82
|
+
150101
|
|
83
|
+
150201
|
|
84
|
+
150303
|
|
85
|
+
150304
|
|
86
|
+
150305
|
|
87
|
+
150306
|
|
88
|
+
150399
|
|
89
|
+
150401
|
|
90
|
+
150403
|
|
91
|
+
150404
|
|
92
|
+
150405
|
|
93
|
+
150406
|
|
94
|
+
150407
|
|
95
|
+
150499
|
|
96
|
+
150501
|
|
97
|
+
150506
|
|
98
|
+
150507
|
|
99
|
+
150508
|
|
100
|
+
150599
|
|
101
|
+
150607
|
|
102
|
+
150611
|
|
103
|
+
150612
|
|
104
|
+
150613
|
|
105
|
+
150614
|
|
106
|
+
150615
|
|
107
|
+
150616
|
|
108
|
+
150617
|
|
109
|
+
150699
|
|
110
|
+
150701
|
|
111
|
+
150702
|
|
112
|
+
150703
|
|
113
|
+
150704
|
|
114
|
+
150799
|
|
115
|
+
150801
|
|
116
|
+
150803
|
|
117
|
+
150805
|
|
118
|
+
150899
|
|
119
|
+
150901
|
|
120
|
+
150903
|
|
121
|
+
150999
|
|
122
|
+
151001
|
|
123
|
+
151102
|
|
124
|
+
151103
|
|
125
|
+
151199
|
|
126
|
+
151201
|
|
127
|
+
151202
|
|
128
|
+
151203
|
|
129
|
+
151204
|
|
130
|
+
151299
|
|
131
|
+
151301
|
|
132
|
+
151302
|
|
133
|
+
151303
|
|
134
|
+
151304
|
|
135
|
+
151305
|
|
136
|
+
151306
|
|
137
|
+
151399
|
|
138
|
+
151401
|
|
139
|
+
151501
|
|
140
|
+
151502
|
|
141
|
+
151503
|
|
142
|
+
151599
|
|
143
|
+
151601
|
|
144
|
+
151701
|
|
145
|
+
151703
|
|
146
|
+
159999
|
|
147
|
+
280501
|
|
148
|
+
280502
|
|
149
|
+
280505
|
|
150
|
+
290201
|
|
151
|
+
290202
|
|
152
|
+
290203
|
|
153
|
+
290204
|
|
154
|
+
290205
|
|
155
|
+
290206
|
|
156
|
+
290207
|
|
157
|
+
290299
|
|
158
|
+
290301
|
|
159
|
+
290302
|
|
160
|
+
290303
|
|
161
|
+
290304
|
|
162
|
+
290305
|
|
163
|
+
290306
|
|
164
|
+
290307
|
|
165
|
+
290399
|
|
166
|
+
290401
|
|
167
|
+
290402
|
|
168
|
+
290403
|
|
169
|
+
290404
|
|
170
|
+
290405
|
|
171
|
+
290406
|
|
172
|
+
290407
|
|
173
|
+
290408
|
|
174
|
+
290409
|
|
175
|
+
290499
|
|
176
|
+
299999
|
|
177
|
+
300101
|
|
178
|
+
300601
|
|
179
|
+
300801
|
|
180
|
+
301001
|
|
181
|
+
301701
|
|
182
|
+
301801
|
|
183
|
+
301901
|
|
184
|
+
302501
|
|
185
|
+
302701
|
|
186
|
+
303001
|
|
187
|
+
303101
|
|
188
|
+
303201
|
|
189
|
+
303301
|
|
190
|
+
303401
|
|
191
|
+
303501
|
|
192
|
+
303801
|
|
193
|
+
303901
|
|
194
|
+
304101
|
|
195
|
+
304301
|
|
196
|
+
304401
|
|
197
|
+
304801
|
|
198
|
+
304901
|
|
199
|
+
305001
|
|
200
|
+
307001
|
|
201
|
+
307101
|
|
202
|
+
307102
|
|
203
|
+
307103
|
|
204
|
+
307104
|
|
205
|
+
307199
|
|
206
|
+
410000
|
|
207
|
+
410101
|
|
208
|
+
410204
|
|
209
|
+
410205
|
|
210
|
+
410299
|
|
211
|
+
410301
|
|
212
|
+
410303
|
|
213
|
+
410399
|
|
214
|
+
419999
|
|
215
|
+
422701
|
|
216
|
+
422702
|
|
217
|
+
422703
|
|
218
|
+
422704
|
|
219
|
+
422705
|
|
220
|
+
422706
|
|
221
|
+
422707
|
|
222
|
+
422708
|
|
223
|
+
422709
|
|
224
|
+
422710
|
|
225
|
+
422799
|
|
226
|
+
422804
|
|
227
|
+
430403
|
|
228
|
+
430406
|
|
229
|
+
430407
|
|
230
|
+
450102
|
|
231
|
+
450301
|
|
232
|
+
450501
|
|
233
|
+
450603
|
|
234
|
+
450702
|
|
235
|
+
490101
|
|
236
|
+
511002
|
|
237
|
+
511005
|
|
238
|
+
511401
|
|
239
|
+
512003
|
|
240
|
+
512004
|
|
241
|
+
512005
|
|
242
|
+
512006
|
|
243
|
+
512007
|
|
244
|
+
512009
|
|
245
|
+
512010
|
|
246
|
+
512202
|
|
247
|
+
512205
|
|
248
|
+
512706
|
|
249
|
+
521301
|
|
250
|
+
521302
|
|
251
|
+
521304
|
|
252
|
+
521399
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Rebuild the fixed DHS six-digit additions lookup from the July 22, 2024 PDF.
|
|
2
|
+
# Run from this directory with: Rscript extract_dhs_stem_cips.R
|
|
3
|
+
|
|
4
|
+
# Source: https://www.ice.gov/doclib/sevis/pdf/stemList2024.pdf
|
|
5
|
+
|
|
6
|
+
args <- commandArgs(trailingOnly = FALSE)
|
|
7
|
+
file_arg <- grep("^--file=", args, value = TRUE)
|
|
8
|
+
script_dir <- if (length(file_arg) == 1) {
|
|
9
|
+
dirname(normalizePath(sub("^--file=", "", file_arg)))
|
|
10
|
+
} else {
|
|
11
|
+
getwd()
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
pdf_path <- file.path(script_dir, "stemList2024.pdf")
|
|
15
|
+
output_path <- file.path(script_dir, "dhs_stem_cip_additions_2024.csv")
|
|
16
|
+
|
|
17
|
+
pdftotext <- Sys.which("pdftotext")
|
|
18
|
+
if (pdftotext == "") {
|
|
19
|
+
stop("Install Poppler so the pdftotext executable is available on PATH.")
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
text_path <- tempfile(fileext = ".txt")
|
|
23
|
+
on.exit(unlink(text_path), add = TRUE)
|
|
24
|
+
status <- system2(pdftotext, c("-layout", shQuote(pdf_path), shQuote(text_path)))
|
|
25
|
+
if (status != 0) {
|
|
26
|
+
stop("pdftotext could not extract the DHS PDF.")
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
pdf_text <- paste(readLines(text_path, warn = FALSE), collapse = "\n")
|
|
30
|
+
cip_codes <- unique(regmatches(
|
|
31
|
+
pdf_text,
|
|
32
|
+
gregexpr("(?<![0-9])[0-9]{2}\\.[0-9]{4}(?![0-9])", pdf_text, perl = TRUE)
|
|
33
|
+
)[[1]])
|
|
34
|
+
|
|
35
|
+
core_families <- c("14", "26", "27", "40")
|
|
36
|
+
cip_codes <- sort(cip_codes[!substr(cip_codes, 1, 2) %in% core_families])
|
|
37
|
+
cip_codes <- gsub("\\.", "", cip_codes)
|
|
38
|
+
|
|
39
|
+
stopifnot(length(cip_codes) == 251)
|
|
40
|
+
stopifnot(!any(substr(cip_codes, 1, 2) %in% core_families))
|
|
41
|
+
stopifnot(all(grepl("^[0-9]{6}$", cip_codes)))
|
|
42
|
+
|
|
43
|
+
write.csv(
|
|
44
|
+
data.frame(cip6 = cip_codes),
|
|
45
|
+
output_path,
|
|
46
|
+
row.names = FALSE,
|
|
47
|
+
quote = FALSE
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
message("Wrote ", length(cip_codes), " DHS six-digit additions to ", output_path)
|
|
Binary file
|
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/aspire.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/check_cmo_apps.do
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/christel_house.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/democracy_prep.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/green_dot.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/helpers.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/kipp_nj.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/mappings.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/rocketship.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260614_new_build_scripts_update/yes_prep.py
RENAMED
|
File without changes
|
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/christel_house.py
RENAMED
|
File without changes
|
{ltc_code-0.2.24 → ltc_code-0.2.25}/src/ltc_code/20260630_census_disclosure/democracy_prep.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|