charter

Author

CRG

Preliminary Analysis: Neighborhood to Charter Transfers

Data Source: Texas Education Agency - Campus Transfer Report

Which Charter Schools Gained Students from Neighborhood Schools

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.3     ✔ tidyr     1.3.1
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(readr)



xfers_campus <- read_csv("xfers_campus_2024_25.csv")
Rows: 316663 Columns: 14
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (12): YEAR, REPORT_REGION, REPORT_DISTRICT, REPORT_DISTRICT_NAME, REPORT...
dbl  (2): REPORT_NUMBER, LINE_GROUP_NUMBER

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#creating a charter not charter flag
xfers_campus <- xfers_campus %>%
  mutate(
    charter_flag = case_when(
      str_detect(REPORT_DISTRICT_NAME, regex("ISD|CISD", ignore_case = TRUE)) ~ "Not Charter",
      str_detect(REPORT_DISTRICT_NAME, regex("ACADEMY|CHARTER|PREP|PREPARATORY|LEADERSHIP|SCHOOL OF EXCELLENCE|PUBLIC SCHOOLS|COMMUNITY SCHOOL|INNOVATION|EXCELLENCE|IMPACT|OUTREACH|VISION|INSPIRE|INC", ignore_case = TRUE)) ~ "Charter",
      TRUE ~ "Not Charter" # Default fallback (safe side)
    )
  )
xfers_campus %>% count(charter_flag)
# A tibble: 2 × 2
  charter_flag      n
  <chr>         <int>
1 Charter       46200
2 Not Charter  270463
library(tidyverse)

isd_to_charter_transfers <- xfers_campus %>%
  filter(
    REPORT_TYPE == "Transfers In From",
    charter_flag == "Charter",
    str_detect(DISTNAME_RES_OR_ATTEND, "ISD|CISD")
  ) %>%
  filter(TRANSFERS_IN_OR_OUT != -999) %>%
  select(
    Sending_ISD = DISTNAME_RES_OR_ATTEND,
    Sending_Campus = CAMPNAME_RES_OR_ATTEND,
    Receiving_Charter_District = REPORT_DISTRICT_NAME,
    Receiving_Charter_Campus = REPORT_CAMPUS_NAME,
    Number_of_Transfers = TRANSFERS_IN_OR_OUT
  )

Charter to ISD Transfers

charter_to_isd_transfers <- xfers_campus %>%
  filter(
    REPORT_TYPE == "Transfers In From",
    str_detect(REPORT_DISTRICT_NAME, "ISD|CISD"),
    charter_flag == "Not Charter"
  ) %>%
  filter(
    str_detect(DISTNAME_RES_OR_ATTEND, regex("ACADEMY|CHARTER|PREP|PREPARATORY|LEADERSHIP|SCHOOL OF EXCELLENCE|PUBLIC SCHOOLS|COMMUNITY SCHOOL|INNOVATION|EXCELLENCE|IMPACT|OUTREACH|VISION|INSPIRE|INC", ignore_case = TRUE))
  ) %>%
  filter(TRANSFERS_IN_OR_OUT != -999) %>%
  select(
    Sending_Charter_District = DISTNAME_RES_OR_ATTEND,
    Sending_Charter_Campus = CAMPNAME_RES_OR_ATTEND,
    Receiving_ISD_District = REPORT_DISTRICT_NAME,
    Receiving_ISD_Campus = REPORT_CAMPUS_NAME,
    Number_of_Transfers = TRANSFERS_IN_OR_OUT
  )

Interactive Tables

DT::datatable(
  isd_to_charter_transfers,
  options = list(pageLength = 15, autoWidth = TRUE, filter = 'top'),
  caption = "Student Transfers: From Neighborhood ISDs to Charter Schools"
)
DT::datatable(
  charter_to_isd_transfers,
  options = list(pageLength = 15, autoWidth = TRUE, filter = 'top'),
  caption = "Student Transfers: From Charter Schools to Neighborhood ISDs"
)

Net Transfer Calculations

district_to_district_transfers <- xfers_campus %>%
  filter(
    REPORT_TYPE == "Transfers In From",
    TRANSFERS_IN_OR_OUT != -999
  ) %>%
  mutate(TRANSFERS_IN_OR_OUT = as.numeric(TRANSFERS_IN_OR_OUT)) %>%   
  group_by(DISTNAME_RES_OR_ATTEND, REPORT_DISTRICT_NAME) %>%
  summarise(
    total_transfers = sum(TRANSFERS_IN_OR_OUT, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(total_transfers))

DT::datatable(
  district_to_district_transfers,
  options = list(pageLength = 15, autoWidth = TRUE, filter = "top"),
  caption = "District-to-District Student Transfer Totals (All Public Districts)"
)

#Top 10 Charter Campuses Receiving Students from Neighborhood ISDs
top_10_charter_campuses <- isd_to_charter_transfers %>%
  mutate(Number_of_Transfers = as.numeric(Number_of_Transfers)) %>%   
  group_by(Receiving_Charter_District, Receiving_Charter_Campus) %>%
  summarise(
    total_transfers_received = sum(Number_of_Transfers, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(total_transfers_received)) %>%
  slice_head(n = 10)

DT::datatable(
  top_10_charter_campuses,
  options = list(pageLength = 10, autoWidth = TRUE, filter = "top"),
  caption = "Top 10 Charter Campuses Receiving Transfers from Neighborhood ISDs"
)
top_10_charter_districts <- isd_to_charter_transfers %>%
  mutate(Number_of_Transfers = as.numeric(Number_of_Transfers)) %>%   # ensure numeric
  group_by(Receiving_Charter_District) %>%
  summarise(
    total_transfers_received = sum(Number_of_Transfers, na.rm = TRUE),
    .groups = "drop"
  ) %>%
  arrange(desc(total_transfers_received)) %>%
  slice_head(n = 10)

DT::datatable(
  top_10_charter_districts,
  options = list(pageLength = 10, autoWidth = TRUE, filter = "top"),
  caption = "Top 10 Charter Districts Receiving Transfers from Neighborhood ISDs"
)