diff --git a/.nojekyll b/.nojekyll index 8477f44..252e374 100644 --- a/.nojekyll +++ b/.nojekyll @@ -1 +1 @@ -f50c4fc0 \ No newline at end of file +83c1aad0 \ No newline at end of file diff --git a/assets/permits_animation.gif b/assets/permits_animation.gif index 911fe1f..0f53bd7 100644 Binary files a/assets/permits_animation.gif and b/assets/permits_animation.gif differ diff --git a/final.html b/final.html index 352077f..7b719d1 100644 --- a/final.html +++ b/final.html @@ -6,7 +6,7 @@ - +
<- permits_bg %>%
- permits_bg_long st_drop_geometry() %>%
- pivot_longer(
- cols = c(starts_with("lag"), dist_to_2022),
- names_to = "Variable",
- values_to = "Value"
-
- )
+filter(year != 2023) %>%
+ st_drop_geometry() %>%
+ pivot_longer(
+ cols = c(starts_with("lag"), dist_to_2022),
+ names_to = "Variable",
+ values_to = "Value"
+
)
-ggscatter(permits_bg_long, x = "permits_count", y = "Value", facet.by = "Variable",
-add = "reg.line",
- add.params = list(color = "blue", fill = "lightgray"),
- conf.int = TRUE
- + stat_cor(method = "pearson", p.accuracy = 0.001, r.accuracy = 0.01) )
<- filter(permits_bg %>% select(-mapname), year < 2022)
permits_train <- filter(permits_bg %>% select(-mapname), year == 2022)
- permits_test
-<- lm(permits_count ~ ., data = st_drop_geometry(permits_train))
- reg
-<- predict(reg, permits_test)
- predictions <- cbind(permits_test, predictions)
- predictions
-<- predictions %>%
- predictions mutate(abs_error = abs(permits_count - predictions),
- pct_error = abs_error / permits_count)
-
-ggplot(predictions, aes(x = permits_count, y = predictions)) +
-geom_point() +
- labs(title = "Predicted vs. Actual Permits",
- subtitle = "2022") +
- geom_smooth(method = "lm", se = FALSE)
We find that our OLS model has an MAE of only MAE: 2.44–not bad for such a simple model! Still, it struggles most in the areas where we most need it to succeed, so we will try to introduce better variables and apply a more complex model to improve our predictions.
+We find that our OLS model has an MAE of only MAE: 2.25–not bad for such a simple model! Still, it struggles most in the areas where we most need it to succeed, so we will try to introduce better variables and apply a more complex model to improve our predictions.
<- permits_bg %>%
+ hmm st_drop_geometry() %>%
+ group_by(year) %>%
+ summarize_all(.funs = list(~sum(is.na(.)))) # Check NA for all columns
tm_shape(acs19) +
-tm_polygons(col = "Percent_Nonwhite", border.alpha = 0, palette = 'viridis', style = "fisher", colorNA = "lightgrey") +
- tm_shape(broad_and_market) +
- tm_lines(col = "lightgrey") +
- tm_layout(frame = FALSE)
# tm_shape(acs22) +
+# tm_polygons(col = "Percent_Nonwhite", border.alpha = 0, palette = mono_5_orange, style = "fisher", colorNA = "lightgrey") +
+# tm_shape(broad_and_market) +
+# tm_lines(col = "lightgrey") +
+# tm_layout(frame = FALSE)
+#
+#
+# tm_shape(acs22) +
+# tm_polygons(col = "Ext_Rent_Burden", border.alpha = 0, palette = mono_5_orange, style = "fisher", colorNA = "lightgrey") +
+# tm_shape(broad_and_market) +
+# tm_lines(col = "lightgrey") +
+# tm_layout(frame = FALSE)
+
+<- rf_predictions %>%
+ rf_predictions mutate(race_comp = case_when(
+ >= .50 ~ "Majority Non-White",
+ percent_nonwhite TRUE ~ "Majority White"
+
+ ))
+ggplot(rf_predictions, aes(y = abs_error, color = race_comp)) +
+geom_boxplot(fill = NA)
<- rf_predictions %>%
- rf_predictions mutate(race_comp = case_when(
- >= .50 ~ "Majority Non-White",
- percent_nonwhite TRUE ~ "Majority White"
-
- ))
-ggplot(rf_predictions, aes(y = abs_error, color = race_comp)) +
-geom_boxplot(fill = NA)
How does this generalize across neighborhoods?
@@ -8735,17 +9630,18 @@<- zoning %>%
- filtered_zoning filter(str_detect(CODE, "RS") | str_detect(CODE, "I"))
-
+filter(str_detect(CODE, "RS") | str_detect(CODE, "I"),
+ != "I2")
CODE
-tm_shape(filtered_zoning) +
-tm_polygons(col = "CODE", border.alpha = 0, colorNA = "lightgrey") +
- tm_shape(broad_and_market) +
- tm_lines(col = "lightgrey") +
- tm_layout(frame = FALSE)
We can extract development predictions at the block level to these parcels and then visualize them by highest need.
@@ -8764,7 +9660,7 @@Furthermore, we can identify properties with high potential for assemblage, which suggests the ability to accomodate high-density, multi-unit housing.
@@ -8829,7 +9725,8 @@275 | -12.16710 | +7575 | +38.37310 | 3 | -604 | -I2 | -|||
858 | -21.58597 | -6 | -1524 | -ICMX | -|||||
903 | -12.94683 | -6 | -1595 | -RSA5 | -|||||
916 | -21.58597 | -8 | -1615 | -ICMX | -|||||
1522 | -11.24437 | -4 | -2559 | +16717 | RSA5 | ||||
1631 | -21.58597 | +4993 | +34.18023 | 3 | -2736 | -IRMX | -|||
1643 | -21.58597 | -6 | -2756 | -ICMX | -|||||
1670 | -21.58597 | -7 | -2803 | +10410 | ICMX | ||||
1671 | -21.58597 | -3 | -2804 | -IRMX | -|||||
1865 | -34.38930 | -3 | -3128 | -IRMX | -|||||
2099 | -12.94683 | -6 | -3492 | -RSA5 | -|||||
2251 | -11.42080 | -4 | -3744 | -IRMX | -|||||
2685 | -12.94683 | -6 | -4533 | -RSA5 | -|||||
3168 | -10.58817 | +4994 | +34.18023 | 3 | -5506 | +10411 | RSA5 | ||
3439 | -21.58597 | -6 | -6067 | -ICMX | -|||||
3554 | -12.94683 | -6 | -6289 | -RSA5 | -|||||
3616 | -21.58597 | +4995 | +34.18023 | 3 | -6405 | -RSA5 | -|||
3836 | -12.94683 | -7 | -6869 | +10412 | ICMX | ||||
3846 | -34.38930 | +5284 | +34.18023 | 3 | -6901 | -ICMX | -|||
3865 | -12.94683 | -6 | -6943 | +11160 | RSA5 | ||||
4155 | -29.69270 | -3 | -7646 | -ICMX | -|||||
4178 | -11.21383 | +1784 | +31.03953 | 3 | -7704 | +3128 | IRMX | ||
4593 | -12.94683 | -6 | -8805 | -RSA5 | -|||||
4697 | -23.03563 | -3 | -9094 | -RSA5 | -|||||
4752 | -16.08273 | -5 | -9244 | -IRMX | -|||||
4800 | -10.58817 | +3669 | +31.03953 | 3 | -9371 | +6901 | ICMX | ||
4910 | -21.58597 | -3 | -9662 | -RSA5 | -|||||
5211 | -35.68783 | +3964 | +25.55263 | 3 | -10411 | +7646 | ICMX | ||
5212 | -35.68783 | -3 | -10412 | +12407 | +25.55263 | +4 | +25776 | RSA5 | |
5213 | -35.68783 | +875 | +21.73580 | 3 | -10413 | +1615 | ICMX | ||
5345 | -18.21887 | +1563 | +21.73580 | 3 | -10760 | +2736 | IRMX | ||
5501 | -39.00537 | +1602 | +21.73580 | 3 | -11150 | -ICMX | +2804 | +IRMX | |
5506 | -35.68783 | +3448 | +21.73580 | 3 | -11161 | +6405 | RSA5 | ||
5616 | -11.24437 | +4700 | +21.73580 | 3 | -11449 | -RSA3 | +9661 | +RSA5 | |
5996 | -11.00043 | +9239 | +21.73580 | 4 | -12339 | -I2 | +20073 | +ICMX | |
6206 | -11.00043 | +4492 | +20.66737 | 3 | -12808 | +9093 | RSA5 | ||
6258 | -11.00043 | +13662 | +19.53400 | 3 | -12932 | -ICMX | +27869 | +IRMX | |
6312 | -16.08273 | -6 | -13058 | -ICMX | +5125 | +19.05720 | +3 | +10759 | +IRMX |
6412 | -23.99983 | +3987 | +15.37260 | 3 | -13314 | +7704 | IRMX | ||
6703 | -22.58767 | +7786 | +14.19870 | 3 | -13979 | -I3 | +17168 | +ICMX | |
6705 | -11.00043 | -3 | -13981 | -RSA3 | -|||||
6720 | -13.26530 | +7893 | +13.97167 | 3 | -14019 | +17408 | RSA5 | ||
6793.2 | -11.00043 | -8 | -14223 | -I2 | -|||||
6794 | -22.58767 | +6008 | +12.64667 | 3 | -14224 | +12931 | ICMX | ||
6808 | -22.58767 | +6444 | +12.64667 | 3 | -14257 | -I2 | +13980 | +RSA3 | |
6855 | -11.00043 | +6589 | +12.64667 | 3 | -14373 | +14372 | RSA5 | ||
6864 | -11.00043 | +6599 | +12.64667 | 3 | 14401 | RSA5 | |||
6865 | -11.00043 | -3 | -14402 | -RSA5 | -|||||
6965 | -13.26530 | +6696 | +12.30283 | 3 | -14649 | +14648 | ICMX | ||
7014 | -12.94683 | -8 | -14748 | -ICMX | -|||||
7192 | -11.24437 | -3 | -15167 | -RSA2 | -|||||
7446 | -39.00537 | -3 | -15720 | -I2 | -|||||
7487 | -11.00043 | -6 | -15820 | -RSA5 | -|||||
7637 | -13.26530 | -3 | -16181 | -RSA5 | -|||||
7885 | -39.00537 | +7335 | +12.30283 | 3 | -16719 | +16179 | RSA5 | ||
8105 | -15.75340 | +9984 | +12.30283 | 3 | -17170 | +21527 | ICMX | ||
8132 | -13.26530 | -3 | -17217 | -ICMX | -|||||
8220 | -15.48503 | +5818 | +11.93540 | 3 | -17410 | +12473 | RSA5 | ||
8543 | -13.56143 | -3 | -18033 | -RSD3 | -|||||
9075 | -13.56143 | -3 | -19078 | -RSA3 | -|||||
9362 | -11.24437 | +8315 | +11.93540 | 3 | -19593 | +18254 | RSA3 | ||
9607 | -21.58597 | -4 | -20075 | -ICMX | -|||||
9802 | -12.16710 | +12923 | +11.93540 | 3 | -20444 | +26627 | RSA5 | ||
9854 | -13.56143 | -4 | -20536 | -RSA2 | -|||||
10377 | -13.26530 | -3 | -21529 | -ICMX | -|||||
10651 | -13.56143 | +4177 | +11.82093 | 3 | -22004 | -RSD1 | +8265 | +IRMX | |
12877 | -29.69270 | +5145 | +11.82093 | 4 | -25778 | -RSA5 | +10795 | +IRMX | |
12929 | -11.24437 | -4 | -25868 | -RSA1 | +4544 | +11.56500 | +5 | +9243 | +IRMX |
13164 | -13.56143 | -3 | -26249 | -RSD1 | +6058 | +11.56500 | +6 | +13057 | +ICMX |
13494 | -10.85073 | +3031 | +11.14353 | 3 | -26759 | +5506 | RSA5 | ||
13599 | -11.24437 | -3 | -26935 | -RSA3 | -|||||
13817 | -11.24437 | -3 | -27284 | -RSA2 | -|||||
13892 | -11.24437 | +4590 | +11.14353 | 3 | -27394 | -RSD3 | +9370 | +ICMX | |
14110 | -13.26530 | +2154 | +10.89000 | 4 | -27776 | -I2 | -|||
14158 | -16.06680 | -3 | -27871 | +3744 | IRMX | ||||
14719.2 | -21.58597 | -28 | -28949 | -I2 | -|||||
14719.3 | -12.94683 | -28 | -28949 | -I2 | -|||||
14720 | -12.94683 | -6 | -28950 | -RSA5 | +6248 | +10.01617 | +4 | +13532 | +ICMX |
Just for shits and giggles, throw in 2024 predictions. (Can use data from 2023.)
+# need to create a new dataframe with year = 2024, spatial and temporal lag based on 2023, and most recent ACS data (2022)
<- permits_bg %>%
- permits_bg_long st_drop_geometry() %>%
- pivot_longer(
- cols = c(starts_with("lag"), dist_to_2022),
- names_to = "Variable",
- values_to = "Value"
-
- )
+filter(year != 2023) %>%
+ st_drop_geometry() %>%
+ pivot_longer(
+ cols = c(starts_with("lag"), dist_to_2022),
+ names_to = "Variable",
+ values_to = "Value"
+
)
-ggscatter(permits_bg_long, x = "permits_count", y = "Value", facet.by = "Variable",
-add = "reg.line",
- add.params = list(color = "blue", fill = "lightgray"),
- conf.int = TRUE
- + stat_cor(method = "pearson", p.accuracy = 0.001, r.accuracy = 0.01) )
<- filter(permits_bg %>% select(-mapname), year < 2022)
permits_train <- filter(permits_bg %>% select(-mapname), year == 2022)
- permits_test
-<- lm(permits_count ~ ., data = st_drop_geometry(permits_train))
- reg
-<- predict(reg, permits_test)
- predictions <- cbind(permits_test, predictions)
- predictions
-<- predictions %>%
- predictions mutate(abs_error = abs(permits_count - predictions),
- pct_error = abs_error / permits_count)
-
-ggplot(predictions, aes(x = permits_count, y = predictions)) +
-geom_point() +
- labs(title = "Predicted vs. Actual Permits",
- subtitle = "2022") +
- geom_smooth(method = "lm", se = FALSE)
We find that our OLS model has an MAE of only MAE: 2.44–not bad for such a simple model! Still, it struggles most in the areas where we most need it to succeed, so we will try to introduce better variables and apply a more complex model to improve our predictions.
+We find that our OLS model has an MAE of only MAE: 2.25–not bad for such a simple model! Still, it struggles most in the areas where we most need it to succeed, so we will try to introduce better variables and apply a more complex model to improve our predictions.
<- permits_bg %>%
+ hmm st_drop_geometry() %>%
+ group_by(year) %>%
+ summarize_all(.funs = list(~sum(is.na(.)))) # Check NA for all columns
tm_shape(acs19) +
-tm_polygons(col = "Percent_Nonwhite", border.alpha = 0, palette = 'viridis', style = "fisher", colorNA = "lightgrey") +
- tm_shape(broad_and_market) +
- tm_lines(col = "lightgrey") +
- tm_layout(frame = FALSE)
# tm_shape(acs22) +
+# tm_polygons(col = "Percent_Nonwhite", border.alpha = 0, palette = mono_5_orange, style = "fisher", colorNA = "lightgrey") +
+# tm_shape(broad_and_market) +
+# tm_lines(col = "lightgrey") +
+# tm_layout(frame = FALSE)
+#
+#
+# tm_shape(acs22) +
+# tm_polygons(col = "Ext_Rent_Burden", border.alpha = 0, palette = mono_5_orange, style = "fisher", colorNA = "lightgrey") +
+# tm_shape(broad_and_market) +
+# tm_lines(col = "lightgrey") +
+# tm_layout(frame = FALSE)
+
+<- rf_predictions %>%
+ rf_predictions mutate(race_comp = case_when(
+ >= .50 ~ "Majority Non-White",
+ percent_nonwhite TRUE ~ "Majority White"
+
+ ))
+ggplot(rf_predictions, aes(y = abs_error, color = race_comp)) +
+geom_boxplot(fill = NA)
<- rf_predictions %>%
- rf_predictions mutate(race_comp = case_when(
- >= .50 ~ "Majority Non-White",
- percent_nonwhite TRUE ~ "Majority White"
-
- ))
-ggplot(rf_predictions, aes(y = abs_error, color = race_comp)) +
-geom_boxplot(fill = NA)
How does this generalize across neighborhoods?
@@ -8735,17 +9630,18 @@<- zoning %>%
- filtered_zoning filter(str_detect(CODE, "RS") | str_detect(CODE, "I"))
-
+filter(str_detect(CODE, "RS") | str_detect(CODE, "I"),
+ != "I2")
CODE
-tm_shape(filtered_zoning) +
-tm_polygons(col = "CODE", border.alpha = 0, colorNA = "lightgrey") +
- tm_shape(broad_and_market) +
- tm_lines(col = "lightgrey") +
- tm_layout(frame = FALSE)
We can extract development predictions at the block level to these parcels and then visualize them by highest need.
@@ -8764,7 +9660,7 @@Furthermore, we can identify properties with high potential for assemblage, which suggests the ability to accomodate high-density, multi-unit housing.
@@ -8829,7 +9725,8 @@275 | -12.16710 | +7575 | +38.37310 | 3 | -604 | -I2 | -|||
858 | -21.58597 | -6 | -1524 | -ICMX | -|||||
903 | -12.94683 | -6 | -1595 | -RSA5 | -|||||
916 | -21.58597 | -8 | -1615 | -ICMX | -|||||
1522 | -11.24437 | -4 | -2559 | +16717 | RSA5 | ||||
1631 | -21.58597 | +4993 | +34.18023 | 3 | -2736 | -IRMX | -|||
1643 | -21.58597 | -6 | -2756 | -ICMX | -|||||
1670 | -21.58597 | -7 | -2803 | +10410 | ICMX | ||||
1671 | -21.58597 | -3 | -2804 | -IRMX | -|||||
1865 | -34.38930 | -3 | -3128 | -IRMX | -|||||
2099 | -12.94683 | -6 | -3492 | -RSA5 | -|||||
2251 | -11.42080 | -4 | -3744 | -IRMX | -|||||
2685 | -12.94683 | -6 | -4533 | -RSA5 | -|||||
3168 | -10.58817 | +4994 | +34.18023 | 3 | -5506 | +10411 | RSA5 | ||
3439 | -21.58597 | -6 | -6067 | -ICMX | -|||||
3554 | -12.94683 | -6 | -6289 | -RSA5 | -|||||
3616 | -21.58597 | +4995 | +34.18023 | 3 | -6405 | -RSA5 | -|||
3836 | -12.94683 | -7 | -6869 | +10412 | ICMX | ||||
3846 | -34.38930 | +5284 | +34.18023 | 3 | -6901 | -ICMX | -|||
3865 | -12.94683 | -6 | -6943 | +11160 | RSA5 | ||||
4155 | -29.69270 | -3 | -7646 | -ICMX | -|||||
4178 | -11.21383 | +1784 | +31.03953 | 3 | -7704 | +3128 | IRMX | ||
4593 | -12.94683 | -6 | -8805 | -RSA5 | -|||||
4697 | -23.03563 | -3 | -9094 | -RSA5 | -|||||
4752 | -16.08273 | -5 | -9244 | -IRMX | -|||||
4800 | -10.58817 | +3669 | +31.03953 | 3 | -9371 | +6901 | ICMX | ||
4910 | -21.58597 | -3 | -9662 | -RSA5 | -|||||
5211 | -35.68783 | +3964 | +25.55263 | 3 | -10411 | +7646 | ICMX | ||
5212 | -35.68783 | -3 | -10412 | +12407 | +25.55263 | +4 | +25776 | RSA5 | |
5213 | -35.68783 | +875 | +21.73580 | 3 | -10413 | +1615 | ICMX | ||
5345 | -18.21887 | +1563 | +21.73580 | 3 | -10760 | +2736 | IRMX | ||
5501 | -39.00537 | +1602 | +21.73580 | 3 | -11150 | -ICMX | +2804 | +IRMX | |
5506 | -35.68783 | +3448 | +21.73580 | 3 | -11161 | +6405 | RSA5 | ||
5616 | -11.24437 | +4700 | +21.73580 | 3 | -11449 | -RSA3 | +9661 | +RSA5 | |
5996 | -11.00043 | +9239 | +21.73580 | 4 | -12339 | -I2 | +20073 | +ICMX | |
6206 | -11.00043 | +4492 | +20.66737 | 3 | -12808 | +9093 | RSA5 | ||
6258 | -11.00043 | +13662 | +19.53400 | 3 | -12932 | -ICMX | +27869 | +IRMX | |
6312 | -16.08273 | -6 | -13058 | -ICMX | +5125 | +19.05720 | +3 | +10759 | +IRMX |
6412 | -23.99983 | +3987 | +15.37260 | 3 | -13314 | +7704 | IRMX | ||
6703 | -22.58767 | +7786 | +14.19870 | 3 | -13979 | -I3 | +17168 | +ICMX | |
6705 | -11.00043 | -3 | -13981 | -RSA3 | -|||||
6720 | -13.26530 | +7893 | +13.97167 | 3 | -14019 | +17408 | RSA5 | ||
6793.2 | -11.00043 | -8 | -14223 | -I2 | -|||||
6794 | -22.58767 | +6008 | +12.64667 | 3 | -14224 | +12931 | ICMX | ||
6808 | -22.58767 | +6444 | +12.64667 | 3 | -14257 | -I2 | +13980 | +RSA3 | |
6855 | -11.00043 | +6589 | +12.64667 | 3 | -14373 | +14372 | RSA5 | ||
6864 | -11.00043 | +6599 | +12.64667 | 3 | 14401 | RSA5 | |||
6865 | -11.00043 | -3 | -14402 | -RSA5 | -|||||
6965 | -13.26530 | +6696 | +12.30283 | 3 | -14649 | +14648 | ICMX | ||
7014 | -12.94683 | -8 | -14748 | -ICMX | -|||||
7192 | -11.24437 | -3 | -15167 | -RSA2 | -|||||
7446 | -39.00537 | -3 | -15720 | -I2 | -|||||
7487 | -11.00043 | -6 | -15820 | -RSA5 | -|||||
7637 | -13.26530 | -3 | -16181 | -RSA5 | -|||||
7885 | -39.00537 | +7335 | +12.30283 | 3 | -16719 | +16179 | RSA5 | ||
8105 | -15.75340 | +9984 | +12.30283 | 3 | -17170 | +21527 | ICMX | ||
8132 | -13.26530 | -3 | -17217 | -ICMX | -|||||
8220 | -15.48503 | +5818 | +11.93540 | 3 | -17410 | +12473 | RSA5 | ||
8543 | -13.56143 | -3 | -18033 | -RSD3 | -|||||
9075 | -13.56143 | -3 | -19078 | -RSA3 | -|||||
9362 | -11.24437 | +8315 | +11.93540 | 3 | -19593 | +18254 | RSA3 | ||
9607 | -21.58597 | -4 | -20075 | -ICMX | -|||||
9802 | -12.16710 | +12923 | +11.93540 | 3 | -20444 | +26627 | RSA5 | ||
9854 | -13.56143 | -4 | -20536 | -RSA2 | -|||||
10377 | -13.26530 | -3 | -21529 | -ICMX | -|||||
10651 | -13.56143 | +4177 | +11.82093 | 3 | -22004 | -RSD1 | +8265 | +IRMX | |
12877 | -29.69270 | +5145 | +11.82093 | 4 | -25778 | -RSA5 | +10795 | +IRMX | |
12929 | -11.24437 | -4 | -25868 | -RSA1 | +4544 | +11.56500 | +5 | +9243 | +IRMX |
13164 | -13.56143 | -3 | -26249 | -RSD1 | +6058 | +11.56500 | +6 | +13057 | +ICMX |
13494 | -10.85073 | +3031 | +11.14353 | 3 | -26759 | +5506 | RSA5 | ||
13599 | -11.24437 | -3 | -26935 | -RSA3 | -|||||
13817 | -11.24437 | -3 | -27284 | -RSA2 | -|||||
13892 | -11.24437 | +4590 | +11.14353 | 3 | -27394 | -RSD3 | +9370 | +ICMX | |
14110 | -13.26530 | +2154 | +10.89000 | 4 | -27776 | -I2 | -|||
14158 | -16.06680 | -3 | -27871 | +3744 | IRMX | ||||
14719.2 | -21.58597 | -28 | -28949 | -I2 | -|||||
14719.3 | -12.94683 | -28 | -28949 | -I2 | -|||||
14720 | -12.94683 | -6 | -28950 | -RSA5 | +6248 | +10.01617 | +4 | +13532 | +ICMX |
Just for shits and giggles, throw in 2024 predictions. (Can use data from 2023.)
+# need to create a new dataframe with year = 2024, spatial and temporal lag based on 2023, and most recent ACS data (2022)