census-loader 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,847 @@
1
+ # fmt: off
2
+ """
3
+ Census Bureau API — Series & Geography Config
4
+ ===============================================
5
+
6
+ Config-driven catalog for a Census API loader. Every entry stores
7
+ exactly what the client needs to build a call like:
8
+
9
+ data = c.acs5.get(series.variables, {**geo, **series.predicates})
10
+
11
+ Hierarchy, smallest to largest. Subcategory dicts merge into category dicts,
12
+ and categories merge into ALL_SERIES:
13
+
14
+ Subcategory: from census_loader.series import TOTAL_POPULATION, AGE_DETAIL
15
+ Category: from census_loader.series import POPULATION, INCOME
16
+ Everything: from census_loader.series import ALL_SERIES
17
+
18
+ Two lookups sit alongside them: CATEGORIES maps a category name to its dict,
19
+ and SUBCATEGORIES maps a category name to its subcategory dicts. Use
20
+ `available()`, `search()` and `info()` from the package root to explore all of
21
+ this interactively rather than reading this file.
22
+
23
+ Most callers never import from here at all: pass series keys, a category name,
24
+ or nothing (for everything) to Config, which resolves them for you.
25
+
26
+ Tuple schema
27
+ ------------
28
+ Each value is a 3-tuple:
29
+
30
+ ("Friendly_Name", # human-readable label
31
+ "dataset_method", # maps to client attr: acs5, acs1, pep, sf1 …
32
+ (<variables>), # tuple of var codes to pass in `get`
33
+ )
34
+
35
+ If a whole table group is wanted, store it as the string "group(BXXXXX)".
36
+ The loader can detect the string vs tuple and branch accordingly.
37
+
38
+ Optional predicates (SAHIE income-to-poverty ratio, PEP age/sex/race
39
+ filters) live in PREDICATES at the bottom — keeps the main dicts lean.
40
+ """
41
+
42
+
43
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
44
+ # ║ FIPS STATE CODES ║
45
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
46
+
47
+ FIPS_STATES = {
48
+ "01": "Alabama", "02": "Alaska", "04": "Arizona",
49
+ "05": "Arkansas", "06": "California", "08": "Colorado",
50
+ "09": "Connecticut", "10": "Delaware", "11": "District of Columbia",
51
+ "12": "Florida", "13": "Georgia", "15": "Hawaii",
52
+ "16": "Idaho", "17": "Illinois", "18": "Indiana",
53
+ "19": "Iowa", "20": "Kansas", "21": "Kentucky",
54
+ "22": "Louisiana", "23": "Maine", "24": "Maryland",
55
+ "25": "Massachusetts", "26": "Michigan", "27": "Minnesota",
56
+ "28": "Mississippi", "29": "Missouri", "30": "Montana",
57
+ "31": "Nebraska", "32": "Nevada", "33": "New Hampshire",
58
+ "34": "New Jersey", "35": "New Mexico", "36": "New York",
59
+ "37": "North Carolina", "38": "North Dakota", "39": "Ohio",
60
+ "40": "Oklahoma", "41": "Oregon", "42": "Pennsylvania",
61
+ "44": "Rhode Island", "45": "South Carolina", "46": "South Dakota",
62
+ "47": "Tennessee", "48": "Texas", "49": "Utah",
63
+ "50": "Vermont", "51": "Virginia", "53": "Washington",
64
+ "54": "West Virginia", "55": "Wisconsin", "56": "Wyoming",
65
+ "72": "Puerto Rico",
66
+ }
67
+
68
+ # Reverse lookup: "California" → "06"
69
+ STATE_FIPS = {v: k for k, v in FIPS_STATES.items()}
70
+
71
+
72
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
73
+ # ║ GEOGRAPHY LEVELS ║
74
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
75
+ #
76
+ # Predicate fragments the loader can plug into the `for` / `in` dict.
77
+ # Finest → coarsest. Each dict is a ready-made geo kwarg.
78
+
79
+ GEO = {
80
+ # ── ACS 5-Year (finest available) ─────────────────────────────────────
81
+ "block_group_in_state": {"for": "block group:*",
82
+ "in": "state:{st}&in=county:{co}&in=tract:{tr}"},
83
+ "tract_in_state": {"for": "tract:*", "in": "state:{st}"},
84
+ "tract_in_county": {"for": "tract:*", "in": "state:{st}&in=county:{co}"},
85
+ "county_in_state": {"for": "county:*", "in": "state:{st}"},
86
+ "county_all": {"for": "county:*"},
87
+ "place_in_state": {"for": "place:*", "in": "state:{st}"},
88
+ "place_all": {"for": "place:*"},
89
+ "msa_all": {"for": "metropolitan statistical area/micropolitan statistical area:*"},
90
+ "congressional_district":{"for": "congressional district:*", "in": "state:{st}"},
91
+ "zcta_all": {"for": "zip code tabulation area:*"},
92
+ "state_all": {"for": "state:*"},
93
+ "us": {"for": "us:1"},
94
+ # ── SAIPE (county + school district) ──────────────────────────────────
95
+ "school_district_in_state": {"for": "school district (unified):*", "in": "state:{st}"},
96
+ }
97
+
98
+ # Which datasets support which geo levels (finest available)
99
+ DATASET_GEO_DEPTH = {
100
+ "acs5": "block_group", # ACS 5-Year Detailed Tables
101
+ "acs5/subject": "tract", # ACS 5-Year Subject Tables
102
+ "acs5/profile": "tract", # ACS 5-Year Data Profiles
103
+ "acs1": "place", # ACS 1-Year (65k+ pop only)
104
+ "pep": "county", # Population Estimates
105
+ "saipe": "county", # + school district via /schdist
106
+ "sahie": "county", # Small Area Health Insurance
107
+ "dec/dhc": "block", # Decennial Demographic & Housing
108
+ "dec/pl": "block", # Decennial Redistricting (P.L. 94-171)
109
+ "cbp": "zipcode", # County Business Patterns
110
+ }
111
+
112
+
113
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
114
+ # ║ POPULATION & AGE ║
115
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
116
+
117
+ TOTAL_POPULATION = {
118
+ "TOTAL_POP": ("Total_Population", "acs5",
119
+ ("B01003_001E",)),
120
+ "POP_BY_AGE_SEX": ("Population_By_Age_Sex", "acs5",
121
+ "group(B01001)"), # 49 vars: male/female × age buckets
122
+ "MEDIAN_AGE": ("Median_Age", "acs5",
123
+ ("B01002_001E",)), # overall
124
+ "MEDIAN_AGE_MALE": ("Median_Age_Male", "acs5",
125
+ ("B01002_002E",)),
126
+ "MEDIAN_AGE_FEMALE": ("Median_Age_Female", "acs5",
127
+ ("B01002_003E",)),
128
+ "POP_UNDER_5": ("Pop_Under_5", "acs5",
129
+ ("B01001_003E", "B01001_027E")), # male + female under 5
130
+ "POP_UNDER_18": ("Pop_Under_18", "acs5",
131
+ ("B09001_001E",)), # children table
132
+ "POP_65_PLUS": ("Pop_65_And_Over", "acs5",
133
+ ("B01001_020E", "B01001_021E", "B01001_022E",
134
+ "B01001_023E", "B01001_024E", "B01001_025E",
135
+ "B01001_044E", "B01001_045E", "B01001_046E",
136
+ "B01001_047E", "B01001_048E", "B01001_049E")),
137
+ "DEPENDENCY_RATIO": ("Age_Dependency_Ratio", "acs5/subject",
138
+ ("S0101_C01_001E", "S0101_C01_022E", # total, under 18
139
+ "S0101_C01_030E")), # 65+
140
+ }
141
+
142
+ AGE_DETAIL = {
143
+ "AGE_GROUPS_5YR": ("Age_5yr_Groups_Full", "acs5",
144
+ "group(B01001)"),
145
+ "AGE_PROFILE": ("Age_Sex_Profile", "acs5/subject",
146
+ "group(S0101)"), # subject table with %s
147
+ "SCHOOL_AGE_5_17": ("School_Age_Pop_5_17", "acs5",
148
+ ("B01001_004E", "B01001_005E", "B01001_006E",
149
+ "B01001_028E", "B01001_029E", "B01001_030E")),
150
+ "WORKING_AGE_25_64": ("Working_Age_Pop_25_64", "acs5/subject",
151
+ ("S0101_C01_025E", "S0101_C01_026E",
152
+ "S0101_C01_027E", "S0101_C01_028E")),
153
+ }
154
+
155
+ POPULATION = {**TOTAL_POPULATION, **AGE_DETAIL}
156
+
157
+
158
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
159
+ # ║ RACE & ETHNICITY ║
160
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
161
+
162
+ RACE = {
163
+ "RACE_TOTAL": ("Race_All_Categories", "acs5",
164
+ "group(B02001)"), # 10 vars
165
+ "WHITE_ALONE": ("Pop_White_Alone", "acs5",
166
+ ("B02001_002E",)),
167
+ "BLACK_ALONE": ("Pop_Black_Alone", "acs5",
168
+ ("B02001_003E",)),
169
+ "AIAN_ALONE": ("Pop_American_Indian_Alaska_Native", "acs5",
170
+ ("B02001_004E",)),
171
+ "ASIAN_ALONE": ("Pop_Asian_Alone", "acs5",
172
+ ("B02001_005E",)),
173
+ "NHPI_ALONE": ("Pop_Native_Hawaiian_Pacific_Islander", "acs5",
174
+ ("B02001_006E",)),
175
+ "OTHER_ALONE": ("Pop_Other_Race_Alone", "acs5",
176
+ ("B02001_007E",)),
177
+ "TWO_OR_MORE": ("Pop_Two_Or_More_Races", "acs5",
178
+ ("B02001_008E",)),
179
+ "ASIAN_DETAIL": ("Asian_Subgroups_Detail", "acs5",
180
+ "group(B02015)"), # Chinese, Indian, Filipino, etc.
181
+ }
182
+
183
+ HISPANIC_ORIGIN = {
184
+ "HISPANIC_TOTAL": ("Hispanic_Or_Latino_Origin", "acs5",
185
+ "group(B03003)"), # Hispanic yes/no
186
+ "HISPANIC_BY_RACE": ("Hispanic_By_Race", "acs5",
187
+ "group(B03002)"), # 21 vars: Hispanic × race
188
+ "HISPANIC_ORIGIN_DETAIL":("Hispanic_Origin_Detail", "acs5",
189
+ "group(B03001)"), # Mexican, Puerto Rican, Cuban…
190
+ "WHITE_NOT_HISPANIC": ("Pop_White_Alone_Not_Hispanic", "acs5",
191
+ ("B03002_003E",)),
192
+ }
193
+
194
+ RACE_ETHNICITY = {**RACE, **HISPANIC_ORIGIN}
195
+
196
+
197
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
198
+ # ║ NATIVITY, CITIZENSHIP & MIGRATION ║
199
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
200
+
201
+ NATIVITY = {
202
+ "NATIVE_FOREIGN_BORN": ("Nativity_Native_vs_Foreign", "acs5",
203
+ "group(B05002)"), # native, foreign born, naturalized
204
+ "FOREIGN_BORN_TOTAL": ("Foreign_Born_Total", "acs5",
205
+ ("B05002_013E",)),
206
+ "CITIZENSHIP_STATUS": ("Citizenship_Status", "acs5",
207
+ "group(B05001)"), # citizen, not citizen, etc.
208
+ "NOT_US_CITIZEN": ("Pop_Not_US_Citizen", "acs5",
209
+ ("B05001_006E",)),
210
+ "PLACE_OF_BIRTH": ("Place_Of_Birth_Foreign", "acs5",
211
+ "group(B05006)"), # by world region / country
212
+ "YEAR_OF_ENTRY": ("Year_Of_Entry_Foreign_Born", "acs5",
213
+ "group(B05005)"),
214
+ }
215
+
216
+ MIGRATION = {
217
+ "GEO_MOBILITY_1YR": ("Geographic_Mobility_Past_Year", "acs5",
218
+ "group(B07001)"), # same house, moved within, etc.
219
+ "MOVERS_SAME_COUNTY": ("Moved_Within_Same_County", "acs5",
220
+ ("B07001_033E",)),
221
+ "MOVERS_DIFF_STATE": ("Moved_From_Different_State", "acs5",
222
+ ("B07001_065E",)),
223
+ "MOVERS_FROM_ABROAD": ("Moved_From_Abroad", "acs5",
224
+ ("B07001_081E",)),
225
+ "MIGRATION_FLOWS": ("County_To_County_Migration_Flows", "acs5/flows",
226
+ ("MOVEDIN", "MOVEDOUT", "MOVEDNET")), # separate dataset
227
+ }
228
+
229
+ NATIVITY_MIGRATION = {**NATIVITY, **MIGRATION}
230
+
231
+
232
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
233
+ # ║ LANGUAGE ║
234
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
235
+
236
+ LANGUAGE = {
237
+ "LANGUAGE_AT_HOME": ("Language_Spoken_At_Home", "acs5",
238
+ "group(B16001)"), # 119 vars: each language × English ability
239
+ "ENGLISH_ABILITY": ("English_Speaking_Ability", "acs5",
240
+ "group(B06007)"),
241
+ "SPEAK_ONLY_ENGLISH": ("Speak_Only_English", "acs5",
242
+ ("B16001_002E",)),
243
+ "SPEAK_SPANISH": ("Speak_Spanish_At_Home", "acs5",
244
+ ("B16001_003E",)),
245
+ "LIMITED_ENGLISH_HH": ("Limited_English_Households", "acs5",
246
+ "group(B16002)"), # linguistically isolated HH
247
+ "LANGUAGE_PROFILE": ("Language_Subject_Table", "acs5/subject",
248
+ "group(S1601)"),
249
+ }
250
+
251
+
252
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
253
+ # ║ EDUCATION ║
254
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
255
+
256
+ SCHOOL_ENROLLMENT = {
257
+ "ENROLLMENT_BY_LEVEL": ("School_Enrollment_By_Level", "acs5",
258
+ "group(B14001)"), # nursery–grad school
259
+ "ENROLLMENT_TYPE": ("School_Enrollment_Public_Private", "acs5",
260
+ "group(B14002)"),
261
+ "ENROLLMENT_PROFILE": ("Enrollment_Subject_Table", "acs5/subject",
262
+ "group(S1401)"),
263
+ }
264
+
265
+ EDUCATIONAL_ATTAINMENT = {
266
+ "ATTAINMENT_25PLUS": ("Educational_Attainment_25Plus", "acs5",
267
+ "group(B15003)"), # 25 levels: no school … doctorate
268
+ "BACHELORS_OR_HIGHER": ("Pct_Bachelors_Or_Higher", "acs5",
269
+ ("B15003_022E", "B15003_023E",
270
+ "B15003_024E", "B15003_025E")), # BA, MA, prof, doctorate
271
+ "HS_GRAD_OR_HIGHER": ("HS_Grad_Or_Higher_Count", "acs5",
272
+ ("B15003_017E", "B15003_018E", "B15003_019E",
273
+ "B15003_020E", "B15003_021E", "B15003_022E",
274
+ "B15003_023E", "B15003_024E", "B15003_025E")),
275
+ "ATTAINMENT_BY_RACE": ("Educational_Attainment_By_Race", "acs5",
276
+ "group(C15002)"), # collapsed, by race iterations
277
+ "ATTAINMENT_BY_SEX": ("Educational_Attainment_By_Sex", "acs5",
278
+ "group(B15002)"),
279
+ "FIELD_OF_DEGREE": ("Field_Of_Bachelors_Degree", "acs5",
280
+ "group(B15012)"), # STEM, business, arts, etc.
281
+ "ATTAINMENT_PROFILE": ("Attainment_Subject_Table", "acs5/subject",
282
+ "group(S1501)"),
283
+ }
284
+
285
+ EDUCATION = {**SCHOOL_ENROLLMENT, **EDUCATIONAL_ATTAINMENT}
286
+
287
+
288
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
289
+ # ║ HOUSEHOLDS & FAMILIES ║
290
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
291
+
292
+ HOUSEHOLD_TYPE = {
293
+ "HOUSEHOLD_TYPE": ("Household_Type", "acs5",
294
+ "group(B11001)"), # family, nonfamily, living alone
295
+ "TOTAL_HOUSEHOLDS": ("Total_Households", "acs5",
296
+ ("B11001_001E",)),
297
+ "FAMILY_HOUSEHOLDS": ("Family_Households", "acs5",
298
+ ("B11001_002E",)),
299
+ "MARRIED_COUPLE_HH": ("Married_Couple_Family_HH", "acs5",
300
+ ("B11001_003E",)),
301
+ "FEMALE_HOUSEHOLDER": ("Female_Householder_No_Spouse", "acs5",
302
+ ("B11001_006E",)),
303
+ "LIVING_ALONE": ("Living_Alone", "acs5",
304
+ ("B11001_008E",)),
305
+ "AVG_HOUSEHOLD_SIZE": ("Average_Household_Size", "acs5",
306
+ ("B25010_001E",)),
307
+ "AVG_FAMILY_SIZE": ("Average_Family_Size", "acs5",
308
+ ("B25010_002E",)),
309
+ }
310
+
311
+ MARITAL_STATUS = {
312
+ "MARITAL_STATUS_15PLUS": ("Marital_Status_15Plus", "acs5",
313
+ "group(B12001)"), # never, now, separated, widowed, divorced
314
+ "MARITAL_BY_SEX_AGE": ("Marital_By_Sex_And_Age", "acs5",
315
+ "group(B12002)"),
316
+ }
317
+
318
+ FERTILITY = {
319
+ "FERTILITY_BY_AGE": ("Women_15_50_Births_Past_Year", "acs5",
320
+ "group(B13002)"),
321
+ "FERTILITY_RATE": ("Fertility_Subject_Table", "acs5/subject",
322
+ "group(S1301)"),
323
+ }
324
+
325
+ HOUSEHOLDS = {**HOUSEHOLD_TYPE, **MARITAL_STATUS, **FERTILITY}
326
+
327
+
328
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
329
+ # ║ INCOME & EARNINGS ║
330
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
331
+
332
+ HOUSEHOLD_INCOME = {
333
+ "MEDIAN_HH_INCOME": ("Median_Household_Income", "acs5",
334
+ ("B19013_001E",)),
335
+ "MEAN_HH_INCOME": ("Mean_Household_Income", "acs5",
336
+ ("B19025_001E",)),
337
+ "HH_INCOME_BRACKETS": ("Household_Income_Distribution", "acs5",
338
+ "group(B19001)"), # 17 income brackets
339
+ "MEDIAN_INCOME_WHITE": ("Median_HH_Income_White", "acs5",
340
+ ("B19013A_001E",)),
341
+ "MEDIAN_INCOME_BLACK": ("Median_HH_Income_Black", "acs5",
342
+ ("B19013B_001E",)),
343
+ "MEDIAN_INCOME_HISPANIC":("Median_HH_Income_Hispanic", "acs5",
344
+ ("B19013I_001E",)),
345
+ "MEDIAN_INCOME_ASIAN": ("Median_HH_Income_Asian", "acs5",
346
+ ("B19013D_001E",)),
347
+ "PER_CAPITA_INCOME": ("Per_Capita_Income", "acs5",
348
+ ("B19301_001E",)),
349
+ "AGGREGATE_INCOME": ("Aggregate_Household_Income", "acs5",
350
+ ("B19025_001E",)),
351
+ }
352
+
353
+ EARNINGS = {
354
+ "MEDIAN_EARNINGS": ("Median_Earnings_Workers", "acs5",
355
+ ("B20002_001E",)),
356
+ "EARNINGS_BY_SEX": ("Earnings_By_Sex_Full_Time", "acs5",
357
+ "group(B20017)"),
358
+ "EARNINGS_BY_EDUCATION":("Earnings_By_Educational_Attainment", "acs5",
359
+ "group(B20004)"),
360
+ "EARNINGS_PROFILE": ("Earnings_Subject_Table", "acs5/subject",
361
+ "group(S2001)"),
362
+ }
363
+
364
+ PUBLIC_ASSISTANCE = {
365
+ "SNAP_HOUSEHOLDS": ("Households_Receiving_SNAP", "acs5",
366
+ "group(B22001)"), # with/without SNAP
367
+ "SNAP_BY_RACE": ("SNAP_By_Race_Of_Householder", "acs5",
368
+ "group(B22005)"),
369
+ "PUBLIC_ASSISTANCE_INC":("Households_Public_Assistance_Income", "acs5",
370
+ "group(B19057)"),
371
+ "SSI_INCOME": ("Households_With_SSI", "acs5",
372
+ "group(B19056)"),
373
+ "SOCIAL_SECURITY": ("Households_With_Social_Security", "acs5",
374
+ "group(B19055)"),
375
+ }
376
+
377
+ INCOME = {**HOUSEHOLD_INCOME, **EARNINGS, **PUBLIC_ASSISTANCE}
378
+
379
+
380
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
381
+ # ║ POVERTY ║
382
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
383
+
384
+ ACS_POVERTY = {
385
+ "POVERTY_STATUS": ("Poverty_Status_All", "acs5",
386
+ "group(B17001)"), # by age × sex
387
+ "POVERTY_RATE_ALL": ("Poverty_Rate_Subject_Table", "acs5/subject",
388
+ "group(S1701)"), # pct below poverty
389
+ "POVERTY_BY_RACE": ("Poverty_By_Race", "acs5",
390
+ ("B17001A_002E", "B17001B_002E", # White, Black
391
+ "B17001D_002E", "B17001I_002E")), # Asian, Hispanic below poverty
392
+ "POVERTY_CHILDREN": ("Poverty_Children_Under_18", "acs5",
393
+ "group(B17006)"),
394
+ "POVERTY_FAMILIES": ("Poverty_Families_By_Type", "acs5",
395
+ "group(B17010)"), # married, female HH, etc.
396
+ "POVERTY_BY_EDUCATION": ("Poverty_By_Educational_Attainment", "acs5",
397
+ "group(B17003)"),
398
+ "RATIO_INCOME_POVERTY": ("Income_To_Poverty_Ratio", "acs5",
399
+ "group(C17002)"), # <0.5, 0.5–0.99, 1.0–1.24…
400
+ }
401
+
402
+ # SAIPE: model-based poverty for ALL counties & school districts (more
403
+ # precise than ACS at small areas). Timeseries — use YEAR= predicate.
404
+ SAIPE_POVERTY = {
405
+ "SAIPE_POVERTY_ALL": ("SAIPE_All_Ages_In_Poverty", "saipe",
406
+ ("SAEPOVALL_PT", "SAEPOVRTALL_PT")), # count, rate
407
+ "SAIPE_POVERTY_0_17": ("SAIPE_Children_0_17_In_Poverty", "saipe",
408
+ ("SAEPOV0_17_PT", "SAEPOVRT0_17_PT")),
409
+ "SAIPE_POVERTY_5_17": ("SAIPE_Children_5_17_In_Poverty", "saipe",
410
+ ("SAEPOV5_17RV_PT", "SAEPOVRT5_17RV_PT")),
411
+ "SAIPE_MEDIAN_HH_INC": ("SAIPE_Median_Household_Income", "saipe",
412
+ ("SAEMHI_PT",)),
413
+ "SAIPE_SCHOOL_DISTRICT":("SAIPE_School_District_Poverty", "saipe/schdist",
414
+ ("SD_NAME", "SAEPOV5_17RV_PT")),
415
+ }
416
+
417
+ POVERTY = {**ACS_POVERTY, **SAIPE_POVERTY}
418
+
419
+
420
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
421
+ # ║ HEALTH INSURANCE ║
422
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
423
+
424
+ ACS_HEALTH_INSURANCE = {
425
+ "HEALTH_INS_COVERAGE": ("Health_Insurance_Coverage_Type", "acs5",
426
+ "group(B27010)"), # by age × coverage type
427
+ "UNINSURED_TOTAL": ("Pop_Without_Health_Insurance", "acs5",
428
+ ("B27010_017E", "B27010_033E",
429
+ "B27010_050E", "B27010_066E")), # uninsured by age group
430
+ "HEALTH_INS_BY_RACE": ("Health_Insurance_By_Race", "acs5/subject",
431
+ "group(S2701)"),
432
+ "HEALTH_INS_PROFILE": ("Health_Insurance_Data_Profile", "acs5/profile",
433
+ ("DP03_0096E", "DP03_0096PE", # with coverage, pct
434
+ "DP03_0099E", "DP03_0099PE")), # no coverage, pct
435
+ }
436
+
437
+ # SAHIE: model-based health insurance for ALL counties.
438
+ # Timeseries — filterable by AGECAT, RACECAT, SEXCAT, IPRCAT.
439
+ SAHIE_HEALTH_INSURANCE = {
440
+ "SAHIE_INSURED_RATE": ("SAHIE_Pct_Insured", "sahie",
441
+ ("NIC_PT", "PCTIC_PT")), # count insured, pct insured
442
+ "SAHIE_UNINSURED_RATE": ("SAHIE_Pct_Uninsured", "sahie",
443
+ ("NUI_PT", "PCTUI_PT")), # count uninsured, pct uninsured
444
+ }
445
+
446
+ HEALTH_INSURANCE = {**ACS_HEALTH_INSURANCE, **SAHIE_HEALTH_INSURANCE}
447
+
448
+
449
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
450
+ # ║ EMPLOYMENT & COMMUTING ║
451
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
452
+
453
+ EMPLOYMENT_STATUS = {
454
+ "EMPLOYMENT_STATUS": ("Employment_Status_16Plus", "acs5",
455
+ "group(B23025)"), # in labor force, employed, unemployed
456
+ "UNEMPLOYMENT_RATE": ("Employment_Status_Subject", "acs5/subject",
457
+ "group(S2301)"), # has % unemployed
458
+ "LABOR_FORCE_PART": ("Labor_Force_Participation", "acs5",
459
+ ("B23025_002E", "B23025_001E")), # in LF / total 16+
460
+ "EMPLOYMENT_BY_SEX": ("Employment_By_Sex", "acs5",
461
+ "group(B23001)"), # sex × age × in LF
462
+ }
463
+
464
+ OCCUPATION_INDUSTRY = {
465
+ "OCCUPATION": ("Occupation_Of_Workers", "acs5",
466
+ "group(C24010)"), # management, service, sales…
467
+ "INDUSTRY": ("Industry_Of_Workers", "acs5",
468
+ "group(C24030)"), # agriculture, construction, mfg…
469
+ "CLASS_OF_WORKER": ("Class_Of_Worker", "acs5",
470
+ "group(B24080)"), # private, govt, self-employed
471
+ "SELF_EMPLOYED": ("Self_Employment", "acs5",
472
+ ("B24080_005E", "B24080_006E", # self-employed incorp / not
473
+ "B24080_012E", "B24080_013E")),
474
+ "WORK_STATUS": ("Work_Status_Past_Year", "acs5",
475
+ "group(B23027)"), # full-time, part-time, didn't work
476
+ }
477
+
478
+ COMMUTING = {
479
+ "COMMUTE_MODE": ("Means_Of_Transportation_To_Work", "acs5",
480
+ "group(B08301)"), # drove alone, carpool, transit, WFH…
481
+ "WORK_FROM_HOME": ("Worked_From_Home", "acs5",
482
+ ("B08301_021E",)),
483
+ "COMMUTE_TIME": ("Travel_Time_To_Work", "acs5",
484
+ "group(B08303)"), # <10 min, 10-14, …, 90+
485
+ "MEDIAN_COMMUTE_TIME": ("Median_Commute_Minutes", "acs5",
486
+ ("B08136_001E",)), # aggregate, divide by workers
487
+ "COMMUTE_PROFILE": ("Commuting_Subject_Table", "acs5/subject",
488
+ "group(S0801)"),
489
+ "PLACE_OF_WORK": ("Place_Of_Work_State_County", "acs5",
490
+ "group(B08007)"), # work in state, out of state
491
+ }
492
+
493
+ EMPLOYMENT = {**EMPLOYMENT_STATUS, **OCCUPATION_INDUSTRY, **COMMUTING}
494
+
495
+
496
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
497
+ # ║ HOUSING CHARACTERISTICS ║
498
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
499
+
500
+ HOUSING_UNITS = {
501
+ "TOTAL_HOUSING_UNITS": ("Total_Housing_Units", "acs5",
502
+ ("B25001_001E",)),
503
+ "OCCUPANCY_STATUS": ("Occupancy_Vacant_Occupied", "acs5",
504
+ "group(B25002)"),
505
+ "VACANCY_STATUS": ("Vacancy_Status_Detail", "acs5",
506
+ "group(B25004)"), # for rent, rented, for sale, etc.
507
+ "UNITS_IN_STRUCTURE": ("Units_In_Structure", "acs5",
508
+ "group(B25024)"), # 1-detached, 2, 3-4, 5-9, 10-19, 20+, mobile
509
+ "YEAR_BUILT": ("Year_Structure_Built", "acs5",
510
+ "group(B25034)"), # 2020+, 2010-19, 2000-09, …
511
+ "ROOMS": ("Number_Of_Rooms", "acs5",
512
+ "group(B25017)"),
513
+ "BEDROOMS": ("Number_Of_Bedrooms", "acs5",
514
+ "group(B25041)"),
515
+ }
516
+
517
+ TENURE = {
518
+ "TENURE_OWN_RENT": ("Tenure_Owner_Renter", "acs5",
519
+ "group(B25003)"), # owner-occupied, renter-occupied
520
+ "HOMEOWNERSHIP_RATE": ("Homeownership_Rate", "acs5",
521
+ ("B25003_002E", "B25003_001E")), # owners / occupied HU
522
+ "TENURE_BY_RACE": ("Tenure_By_Race", "acs5",
523
+ ("B25003A_002E", "B25003A_003E", # White own/rent
524
+ "B25003B_002E", "B25003B_003E", # Black own/rent
525
+ "B25003D_002E", "B25003D_003E", # Asian own/rent
526
+ "B25003I_002E", "B25003I_003E")), # Hispanic own/rent
527
+ "TENURE_BY_AGE": ("Tenure_By_Age_Of_Householder", "acs5",
528
+ "group(B25007)"),
529
+ }
530
+
531
+ HOME_VALUE = {
532
+ "MEDIAN_HOME_VALUE": ("Median_Home_Value_Owner_Occ", "acs5",
533
+ ("B25077_001E",)),
534
+ "HOME_VALUE_DIST": ("Home_Value_Distribution", "acs5",
535
+ "group(B25075)"), # <$10k, $10k-14.9k, …, $2M+
536
+ "MEDIAN_RENT": ("Median_Gross_Rent", "acs5",
537
+ ("B25064_001E",)),
538
+ "RENT_DISTRIBUTION": ("Gross_Rent_Distribution", "acs5",
539
+ "group(B25063)"),
540
+ "RENT_BURDEN": ("Gross_Rent_As_Pct_Income", "acs5",
541
+ "group(B25070)"), # <10%, 10-14.9%, …, 50%+
542
+ "OWNER_COST_BURDEN": ("Owner_Costs_As_Pct_Income_Mortgage", "acs5",
543
+ "group(B25091)"), # <10%, 10-14.9%, …, 50%+
544
+ "MORTGAGE_STATUS": ("Mortgage_Status", "acs5",
545
+ "group(B25081)"), # with/without mortgage
546
+ }
547
+
548
+ HOUSING_INFRASTRUCTURE = {
549
+ "PLUMBING": ("Plumbing_Facilities", "acs5",
550
+ "group(B25047)"),
551
+ "KITCHEN": ("Kitchen_Facilities", "acs5",
552
+ "group(B25051)"),
553
+ "HEATING_FUEL": ("House_Heating_Fuel", "acs5",
554
+ "group(B25040)"), # gas, electric, oil, wood, solar, none
555
+ "VEHICLES_AVAILABLE": ("Vehicles_Available", "acs5",
556
+ "group(B25044)"), # 0, 1, 2, 3+
557
+ "NO_VEHICLE": ("Households_No_Vehicle", "acs5",
558
+ ("B25044_003E", "B25044_010E")), # owner 0 + renter 0
559
+ "INTERNET_ACCESS": ("Internet_Access_Type", "acs5/subject",
560
+ "group(S2801)"), # broadband, cellular, none
561
+ "COMPUTER_IN_HH": ("Computer_And_Internet_In_HH", "acs5",
562
+ "group(B28001)"), # has computer, no computer
563
+ }
564
+
565
+ HOUSING = {**HOUSING_UNITS, **TENURE, **HOME_VALUE, **HOUSING_INFRASTRUCTURE}
566
+
567
+
568
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
569
+ # ║ DISABILITY ║
570
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
571
+
572
+ DISABILITY = {
573
+ "DISABILITY_STATUS": ("Disability_Status_By_Age", "acs5",
574
+ "group(B18101)"), # with/without by age
575
+ "DISABILITY_TYPE": ("Disability_Type_By_Age", "acs5",
576
+ "group(B18102)"), # hearing, vision, cognitive, ambulatory…
577
+ "DISABILITY_BY_SEX": ("Disability_By_Sex", "acs5/subject",
578
+ "group(S1810)"),
579
+ "DISABILITY_EMPLOYMENT":("Disability_Employment_Status", "acs5",
580
+ "group(B18120)"), # employed, unemployed, not in LF
581
+ "DISABILITY_PROFILE": ("Disability_Data_Profile", "acs5/profile",
582
+ ("DP02_0072E", "DP02_0072PE")), # civilian with disability, pct
583
+ }
584
+
585
+
586
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
587
+ # ║ VETERANS ║
588
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
589
+
590
+ VETERANS = {
591
+ "VETERAN_STATUS": ("Veteran_Status_18Plus", "acs5",
592
+ "group(B21001)"), # veteran, nonveteran × sex
593
+ "VETERAN_PERIOD": ("Veteran_By_Period_Of_Service", "acs5",
594
+ "group(B21002)"), # Gulf War, Vietnam, Korea, WWII…
595
+ "VETERAN_DISABILITY": ("Veteran_Disability_Status", "acs5",
596
+ "group(B21100)"), # with/without service-connected
597
+ "VETERAN_PROFILE": ("Veteran_Subject_Table", "acs5/subject",
598
+ "group(S2101)"),
599
+ }
600
+
601
+
602
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
603
+ # ║ POPULATION ESTIMATES PROGRAM (PEP) ║
604
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
605
+ #
606
+ # Annual intercensal estimates. Dataset = pep/charv (2020-base vintage).
607
+ # Filterable by AGE, SEX, RACE, HISP, POPGROUP predicates.
608
+ # Available for nation, states, counties.
609
+
610
+ PEP_POPULATION = {
611
+ "PEP_TOTAL": ("PEP_Total_Population", "pep",
612
+ ("POP",)),
613
+ "PEP_BY_AGE_SEX": ("PEP_By_Age_Sex", "pep",
614
+ ("POP", "AGE", "SEX")),
615
+ "PEP_BY_RACE_HISP": ("PEP_By_Race_Hispanic", "pep",
616
+ ("POP", "RACE", "HISP")),
617
+ "PEP_BY_POPGROUP": ("PEP_By_Population_Group", "pep",
618
+ ("POP", "POPGROUP")),
619
+ "PEP_COMPONENTS": ("PEP_Components_Of_Change", "pep",
620
+ ("BIRTHS", "DEATHS", "NATURALINC",
621
+ "INTERNATIONALMIG", "DOMESTICMIG",
622
+ "NETMIG", "NPOPCHG")),
623
+ "PEP_HOUSING_UNITS": ("PEP_Housing_Units", "pep",
624
+ ("HUEST",)),
625
+ }
626
+
627
+
628
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
629
+ # ║ DECENNIAL CENSUS ║
630
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
631
+ #
632
+ # 2020 Decennial — two main files:
633
+ # dec/pl = P.L. 94-171 Redistricting Data (race/ethnicity + voting age)
634
+ # dec/dhc = Demographic & Housing Characteristics
635
+ # Available down to BLOCK level.
636
+
637
+ DECENNIAL_REDISTRICTING = {
638
+ "DEC_TOTAL_POP": ("Dec2020_Total_Pop", "dec/pl",
639
+ ("P1_001N",)), # total pop
640
+ "DEC_RACE": ("Dec2020_Race", "dec/pl",
641
+ ("P1_003N", "P1_004N", "P1_005N", # White, Black, AIAN
642
+ "P1_006N", "P1_007N", "P1_008N", # Asian, NHPI, Other
643
+ "P1_009N")), # Two+
644
+ "DEC_HISPANIC": ("Dec2020_Hispanic_Origin", "dec/pl",
645
+ ("P2_002N", "P2_003N")), # Hispanic, Not Hispanic
646
+ "DEC_VOTING_AGE": ("Dec2020_Voting_Age_18Plus", "dec/pl",
647
+ ("P3_001N",)),
648
+ "DEC_HOUSING_OCC": ("Dec2020_Housing_Occupancy", "dec/pl",
649
+ ("H1_001N", "H1_002N", "H1_003N")), # total, occupied, vacant
650
+ }
651
+
652
+ DECENNIAL_DHC = {
653
+ "DEC_AGE_SEX": ("Dec2020_Age_By_Sex", "dec/dhc",
654
+ "group(P12)"), # single-year-of-age × sex
655
+ "DEC_HOUSEHOLD_TYPE": ("Dec2020_Household_Type", "dec/dhc",
656
+ "group(P20)"),
657
+ "DEC_GROUP_QUARTERS": ("Dec2020_Group_Quarters", "dec/dhc",
658
+ "group(P42)"), # institutional, noninstitutional
659
+ "DEC_TENURE": ("Dec2020_Tenure", "dec/dhc",
660
+ "group(H4)"), # owner, renter
661
+ }
662
+
663
+ DECENNIAL = {**DECENNIAL_REDISTRICTING, **DECENNIAL_DHC}
664
+
665
+
666
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
667
+ # ║ DATA PROFILES (broad summary tables) ║
668
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
669
+ #
670
+ # Each DP table is a one-stop shop for a broad topic. Good for dashboards.
671
+
672
+ DATA_PROFILES = {
673
+ "DP_SOCIAL": ("Profile_Social_Characteristics", "acs5/profile",
674
+ "group(DP02)"), # education, marital, ancestry, language…
675
+ "DP_ECONOMIC": ("Profile_Economic_Characteristics", "acs5/profile",
676
+ "group(DP03)"), # employment, income, industry, health ins…
677
+ "DP_HOUSING": ("Profile_Housing_Characteristics", "acs5/profile",
678
+ "group(DP04)"), # tenure, value, rent, structure, heating…
679
+ "DP_DEMOGRAPHIC": ("Profile_Demographic_Characteristics", "acs5/profile",
680
+ "group(DP05)"), # sex, age, race, Hispanic origin
681
+ }
682
+
683
+
684
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
685
+ # ║ PREDICATE FILTERS ║
686
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
687
+ #
688
+ # For datasets that use categorical predicates (PEP, SAHIE, etc.), store
689
+ # the valid values here so the loader can loop or filter.
690
+
691
+ PREDICATES = {
692
+ # ── PEP race codes ────────────────────────────────────────────────────
693
+ "PEP_RACE": {
694
+ 0: "All_Races",
695
+ 1: "White_Alone",
696
+ 2: "Black_Alone",
697
+ 3: "American_Indian_Alaska_Native_Alone",
698
+ 4: "Asian_Alone",
699
+ 5: "Native_Hawaiian_Pacific_Islander_Alone",
700
+ 6: "Two_Or_More_Races",
701
+ },
702
+ # ── PEP Hispanic origin ──────────────────────────────────────────────
703
+ "PEP_HISP": {
704
+ 0: "Total",
705
+ 1: "Not_Hispanic",
706
+ 2: "Hispanic",
707
+ },
708
+ # ── PEP sex ───────────────────────────────────────────────────────────
709
+ "PEP_SEX": {
710
+ 0: "Both_Sexes",
711
+ 1: "Male",
712
+ 2: "Female",
713
+ },
714
+ # ── SAHIE age category ────────────────────────────────────────────────
715
+ "SAHIE_AGECAT": {
716
+ 0: "Under_65",
717
+ 1: "18_to_64",
718
+ 2: "40_to_64",
719
+ 3: "50_to_64",
720
+ 4: "Under_19",
721
+ 5: "21_to_64",
722
+ },
723
+ # ── SAHIE income-to-poverty ratio ─────────────────────────────────────
724
+ "SAHIE_IPRCAT": {
725
+ 0: "All_Incomes",
726
+ 1: "At_Or_Below_200pct_FPL",
727
+ 2: "At_Or_Below_250pct_FPL",
728
+ 3: "At_Or_Below_138pct_FPL",
729
+ 4: "At_Or_Below_400pct_FPL",
730
+ 5: "Between_138_and_400pct_FPL",
731
+ },
732
+ # ── SAHIE race/ethnicity ──────────────────────────────────────────────
733
+ "SAHIE_RACECAT": {
734
+ 0: "All_Races",
735
+ 1: "White_Alone_Not_Hispanic",
736
+ 2: "Black_Alone",
737
+ 3: "Hispanic_Any_Race",
738
+ },
739
+ # ── SAHIE sex ─────────────────────────────────────────────────────────
740
+ "SAHIE_SEXCAT": {
741
+ 0: "Both_Sexes",
742
+ 1: "Male",
743
+ 2: "Female",
744
+ },
745
+ }
746
+
747
+
748
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
749
+ # ║ COMPOSITES ║
750
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
751
+
752
+ ALL_SERIES = {
753
+ **POPULATION,
754
+ **RACE_ETHNICITY,
755
+ **NATIVITY_MIGRATION,
756
+ **LANGUAGE,
757
+ **EDUCATION,
758
+ **HOUSEHOLDS,
759
+ **INCOME,
760
+ **POVERTY,
761
+ **HEALTH_INSURANCE,
762
+ **EMPLOYMENT,
763
+ **HOUSING,
764
+ **DISABILITY,
765
+ **VETERANS,
766
+ **PEP_POPULATION,
767
+ **DECENNIAL,
768
+ **DATA_PROFILES,
769
+ }
770
+
771
+ # ── Category lookup (top-level) ───────────────────────────────────────────
772
+ CATEGORIES = {
773
+ "POPULATION": POPULATION,
774
+ "RACE_ETHNICITY": RACE_ETHNICITY,
775
+ "NATIVITY_MIGRATION":NATIVITY_MIGRATION,
776
+ "LANGUAGE": LANGUAGE,
777
+ "EDUCATION": EDUCATION,
778
+ "HOUSEHOLDS": HOUSEHOLDS,
779
+ "INCOME": INCOME,
780
+ "POVERTY": POVERTY,
781
+ "HEALTH_INSURANCE": HEALTH_INSURANCE,
782
+ "EMPLOYMENT": EMPLOYMENT,
783
+ "HOUSING": HOUSING,
784
+ "DISABILITY": DISABILITY,
785
+ "VETERANS": VETERANS,
786
+ "PEP_POPULATION": PEP_POPULATION,
787
+ "DECENNIAL": DECENNIAL,
788
+ "DATA_PROFILES": DATA_PROFILES,
789
+ }
790
+
791
+ # ── Subcategory lookup (nested, with variable references) ─────────────────
792
+ SUBCATEGORIES = {
793
+ "POPULATION": {
794
+ "TOTAL_POPULATION": TOTAL_POPULATION,
795
+ "AGE_DETAIL": AGE_DETAIL,
796
+ },
797
+ "RACE_ETHNICITY": {
798
+ "RACE": RACE,
799
+ "HISPANIC_ORIGIN": HISPANIC_ORIGIN,
800
+ },
801
+ "NATIVITY_MIGRATION": {
802
+ "NATIVITY": NATIVITY,
803
+ "MIGRATION": MIGRATION,
804
+ },
805
+ "LANGUAGE": {},
806
+ "EDUCATION": {
807
+ "SCHOOL_ENROLLMENT": SCHOOL_ENROLLMENT,
808
+ "EDUCATIONAL_ATTAINMENT":EDUCATIONAL_ATTAINMENT,
809
+ },
810
+ "HOUSEHOLDS": {
811
+ "HOUSEHOLD_TYPE": HOUSEHOLD_TYPE,
812
+ "MARITAL_STATUS": MARITAL_STATUS,
813
+ "FERTILITY": FERTILITY,
814
+ },
815
+ "INCOME": {
816
+ "HOUSEHOLD_INCOME": HOUSEHOLD_INCOME,
817
+ "EARNINGS": EARNINGS,
818
+ "PUBLIC_ASSISTANCE": PUBLIC_ASSISTANCE,
819
+ },
820
+ "POVERTY": {
821
+ "ACS_POVERTY": ACS_POVERTY,
822
+ "SAIPE_POVERTY": SAIPE_POVERTY,
823
+ },
824
+ "HEALTH_INSURANCE": {
825
+ "ACS_HEALTH_INSURANCE": ACS_HEALTH_INSURANCE,
826
+ "SAHIE_HEALTH_INSURANCE":SAHIE_HEALTH_INSURANCE,
827
+ },
828
+ "EMPLOYMENT": {
829
+ "EMPLOYMENT_STATUS": EMPLOYMENT_STATUS,
830
+ "OCCUPATION_INDUSTRY": OCCUPATION_INDUSTRY,
831
+ "COMMUTING": COMMUTING,
832
+ },
833
+ "HOUSING": {
834
+ "HOUSING_UNITS": HOUSING_UNITS,
835
+ "TENURE": TENURE,
836
+ "HOME_VALUE": HOME_VALUE,
837
+ "HOUSING_INFRASTRUCTURE":HOUSING_INFRASTRUCTURE,
838
+ },
839
+ "DISABILITY": {},
840
+ "VETERANS": {},
841
+ "PEP_POPULATION": {},
842
+ "DECENNIAL": {
843
+ "DECENNIAL_REDISTRICTING": DECENNIAL_REDISTRICTING,
844
+ "DECENNIAL_DHC": DECENNIAL_DHC,
845
+ },
846
+ "DATA_PROFILES": {},
847
+ }