In this notebook, I broke down some 2023 Consumer Expenditure Survey data, to analyze child care expenditure share.

Below, I downloaded the necessary packages for data cleaning and uploaded the data set.

library(dplyr)
library(patchwork)
data_dir <- "/Users/rileystern/Downloads/intrvw23 3/"
list.files(data_dir)
 [1] "expn23"       "fmli232.csv"  "fmli233.csv"  "fmli234.csv"  "fmli241.csv"  "itbi232.csv" 
 [7] "itbi233.csv"  "itbi234.csv"  "itbi241.csv"  "itii232.csv"  "itii233.csv"  "itii234.csv" 
[13] "itii241.csv"  "memi232.csv"  "memi233.csv"  "memi234.csv"  "memi241.csv"  "mtbi232.csv" 
[19] "mtbi233.csv"  "mtbi234.csv"  "mtbi241.csv"  "ntaxi232.csv" "ntaxi233.csv" "ntaxi234.csv"
[25] "ntaxi241.csv" "para23"      

I downloaded the 2023 CES data and used the MTBI (monthly expenditures) and FMLI (family-level information) files. Then, I merged them by user ID. The monthly expenditures give a summary of where expenditures lie for respondants and the family-level information provides information about families needing childcare.

fmli_files <- list.files(data_dir, pattern = "^fmli.*\\.csv$", full.names = TRUE)
mtbi_files <- list.files(data_dir, pattern = "^mtbi.*\\.csv$", full.names = TRUE)




read_and_combine <- function(file_list) {
  combined <- lapply(file_list, function(f) read.csv(f, stringsAsFactors = FALSE)) %>%
    bind_rows()
  return(combined)
}

fmli_all <- read_and_combine(fmli_files)
mtbi_all <- read_and_combine(mtbi_files)

merged_data <- inner_join(mtbi_all, fmli_all, by = "NEWID")

Next, I downloaded the necessary graph package.

library(ggplot2)

From the FMLI and MTBI merged dataframe I created, I selected specific variables that would be relevant to childcare expenditure analysis. These include the user ID (NEWID), amount spent on childcare last quarter (BBYDAYPQ), total expenditure for the quarter (TOTEXPPQ), and age of children (CHILDAGE). I initally also included the variable for income class (INCLASS2), but later found this wasn’t necessary.

childcare_data <- merged_data %>%
  select(NEWID, TOTEXPPQ, BBYDAYPQ, INCLASS2, CHILDAGE)

To clean the data, I filtered out the empty or NA responses, and also required CHILDAGE to be greater than 0, so that families without children would not be counted. In future, perhaps there should be an upper bound for this as well. I also created a new column in this dataframe called expend_quintile, which takes the TOTEXPPQ column and divides it into quintiles, and then assigns each user a quintile based on how much they expend.

childcare_users <- childcare_data %>%
  filter(!is.na(TOTEXPPQ), !is.na(BBYDAYPQ), !is.na(INCLASS2), CHILDAGE > 0) %>%
  mutate(
    childcare_share = BBYDAYPQ / TOTEXPPQ,
    expend_quintile = ntile(TOTEXPPQ, 5)
  )

Then, I created a another dataframe based off the childcare_users, that isolated only those families that pay for childcare- i.e. not those who get it free.

childcare_payers <- childcare_users %>%
  filter(BBYDAYPQ > 0)

Next, I found averages for both dataframes, for these expenditures to be able to graph.

summary_users <- childcare_users %>%
  group_by(expend_quintile) %>%
  summarise(avg_share = mean(childcare_share, na.rm = TRUE))

summary_payers <- childcare_payers %>%
  group_by(expend_quintile) %>%
  summarise(avg_share = mean(childcare_share, na.rm = TRUE))

Here, I created a consistent axis for the graphs.

max_share <- max(c(summary_users$avg_share, summary_payers$avg_share), na.rm = TRUE)

The first plot I created features all childcare users, regardless of pay or not.

p1 <- ggplot(summary_users, aes(x = factor(expend_quintile), y = avg_share)) +
  geom_col(fill = "pink") +
  labs(
    title = "Average Childcare Share (All Users, Including Free)",
    x = "Expenditure Quintile",
    y = "Average Share of Expenditures"
  ) +
  theme_minimal() +
  scale_y_continuous(limits = c(0, max_share))

The second plot has just the payers.

p2 <- ggplot(summary_payers, aes(x = factor(expend_quintile), y = avg_share)) +
  geom_col(fill = "lavender") +
  labs(
    title = "Average Childcare Share (Spending Households Only)",
    x = "Expenditure Quintile",
    y = "Average Share of Expenditures"
  ) +
  theme_minimal() +
  scale_y_continuous(limits = c(0, max_share))

install.packages("clipr")
trying URL 'https://cran.rstudio.com/bin/macosx/big-sur-arm64/contrib/4.4/clipr_0.8.0.tgz'
Content type 'application/x-gzip' length 51681 bytes (50 KB)
==================================================
downloaded 50 KB

The downloaded binary packages are in
    /var/folders/rx/1zr50b_d1s78nny7x6_83j5m0000gn/T//RtmprM34l1/downloaded_packages
library(clipr)
library(knitr)

knitr::include_graphics("~/Desktop/Childcare-Affordability.png")

NA
LS0tCnRpdGxlOiAiQmFzaWMgQ2hpbGRjYXJlIEV4cGVuZGl0dXJlIEFuYWx5c2lzIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCkluIHRoaXMgbm90ZWJvb2ssIEkgYnJva2UgZG93biBzb21lIDIwMjMgQ29uc3VtZXIgRXhwZW5kaXR1cmUgU3VydmV5IGRhdGEsIHRvIGFuYWx5emUgY2hpbGQgY2FyZSBleHBlbmRpdHVyZSBzaGFyZS4gCgpCZWxvdywgSSBkb3dubG9hZGVkIHRoZSBuZWNlc3NhcnkgcGFja2FnZXMgZm9yIGRhdGEgY2xlYW5pbmcgYW5kIHVwbG9hZGVkIHRoZSBkYXRhIHNldC4gCmBgYHtyfQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KHBhdGNod29yaykKZGF0YV9kaXIgPC0gIi9Vc2Vycy9yaWxleXN0ZXJuL0Rvd25sb2Fkcy9pbnRydncyMyAzLyIKbGlzdC5maWxlcyhkYXRhX2RpcikKYGBgCiBJIGRvd25sb2FkZWQgdGhlIDIwMjMgQ0VTIGRhdGEgYW5kIHVzZWQgdGhlIE1UQkkgKG1vbnRobHkgZXhwZW5kaXR1cmVzKSBhbmQgRk1MSSAoZmFtaWx5LWxldmVsIGluZm9ybWF0aW9uKSBmaWxlcy4gVGhlbiwgSSBtZXJnZWQgdGhlbSBieSB1c2VyIElELiBUaGUgbW9udGhseSBleHBlbmRpdHVyZXMgZ2l2ZSBhIHN1bW1hcnkgb2Ygd2hlcmUgZXhwZW5kaXR1cmVzIGxpZSBmb3IgcmVzcG9uZGFudHMgYW5kIHRoZSBmYW1pbHktbGV2ZWwgaW5mb3JtYXRpb24gcHJvdmlkZXMgaW5mb3JtYXRpb24gYWJvdXQgZmFtaWxpZXMgbmVlZGluZyBjaGlsZGNhcmUuIAogCmBgYHtyfQpmbWxpX2ZpbGVzIDwtIGxpc3QuZmlsZXMoZGF0YV9kaXIsIHBhdHRlcm4gPSAiXmZtbGkuKlxcLmNzdiQiLCBmdWxsLm5hbWVzID0gVFJVRSkKbXRiaV9maWxlcyA8LSBsaXN0LmZpbGVzKGRhdGFfZGlyLCBwYXR0ZXJuID0gIl5tdGJpLipcXC5jc3YkIiwgZnVsbC5uYW1lcyA9IFRSVUUpCgoKCgpyZWFkX2FuZF9jb21iaW5lIDwtIGZ1bmN0aW9uKGZpbGVfbGlzdCkgewogIGNvbWJpbmVkIDwtIGxhcHBseShmaWxlX2xpc3QsIGZ1bmN0aW9uKGYpIHJlYWQuY3N2KGYsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkpICU+JQogICAgYmluZF9yb3dzKCkKICByZXR1cm4oY29tYmluZWQpCn0KCmZtbGlfYWxsIDwtIHJlYWRfYW5kX2NvbWJpbmUoZm1saV9maWxlcykKbXRiaV9hbGwgPC0gcmVhZF9hbmRfY29tYmluZShtdGJpX2ZpbGVzKQoKbWVyZ2VkX2RhdGEgPC0gaW5uZXJfam9pbihtdGJpX2FsbCwgZm1saV9hbGwsIGJ5ID0gIk5FV0lEIikKYGBgCgpOZXh0LCBJIGRvd25sb2FkZWQgdGhlIG5lY2Vzc2FyeSBncmFwaCBwYWNrYWdlLiAKCmBgYHtyfQpsaWJyYXJ5KGdncGxvdDIpCmBgYAoKRnJvbSB0aGUgRk1MSSBhbmQgTVRCSSBtZXJnZWQgZGF0YWZyYW1lIEkgY3JlYXRlZCwgSSBzZWxlY3RlZCBzcGVjaWZpYyB2YXJpYWJsZXMgdGhhdCB3b3VsZCBiZSByZWxldmFudCB0byBjaGlsZGNhcmUgZXhwZW5kaXR1cmUgYW5hbHlzaXMuIFRoZXNlIGluY2x1ZGUgdGhlIHVzZXIgSUQgKE5FV0lEKSwgYW1vdW50IHNwZW50IG9uIGNoaWxkY2FyZSBsYXN0IHF1YXJ0ZXIgKEJCWURBWVBRKSwgdG90YWwgZXhwZW5kaXR1cmUgZm9yIHRoZSBxdWFydGVyIChUT1RFWFBQUSksIGFuZCBhZ2Ugb2YgY2hpbGRyZW4gKENISUxEQUdFKS4gSSBpbml0YWxseSBhbHNvIGluY2x1ZGVkIHRoZSB2YXJpYWJsZSBmb3IgaW5jb21lIGNsYXNzIChJTkNMQVNTMiksIGJ1dCBsYXRlciBmb3VuZCB0aGlzIHdhc24ndCBuZWNlc3NhcnkuCmBgYHtyfQpjaGlsZGNhcmVfZGF0YSA8LSBtZXJnZWRfZGF0YSAlPiUKICBzZWxlY3QoTkVXSUQsIFRPVEVYUFBRLCBCQllEQVlQUSwgSU5DTEFTUzIsIENISUxEQUdFKQpgYGAKClRvIGNsZWFuIHRoZSBkYXRhLCBJIGZpbHRlcmVkIG91dCB0aGUgZW1wdHkgb3IgTkEgcmVzcG9uc2VzLCBhbmQgYWxzbyByZXF1aXJlZCBDSElMREFHRSB0byBiZSBncmVhdGVyIHRoYW4gMCwgc28gdGhhdCBmYW1pbGllcyB3aXRob3V0IGNoaWxkcmVuIHdvdWxkIG5vdCBiZSBjb3VudGVkLiBJbiBmdXR1cmUsIHBlcmhhcHMgdGhlcmUgc2hvdWxkIGJlIGFuIHVwcGVyIGJvdW5kIGZvciB0aGlzIGFzIHdlbGwuIEkgYWxzbyBjcmVhdGVkIGEgbmV3IGNvbHVtbiBpbiB0aGlzIGRhdGFmcmFtZSBjYWxsZWQgZXhwZW5kX3F1aW50aWxlLCB3aGljaCB0YWtlcyB0aGUgVE9URVhQUFEgY29sdW1uIGFuZCBkaXZpZGVzIGl0IGludG8gcXVpbnRpbGVzLCBhbmQgdGhlbiBhc3NpZ25zIGVhY2ggdXNlciBhIHF1aW50aWxlIGJhc2VkIG9uIGhvdyBtdWNoIHRoZXkgZXhwZW5kLiAKCmBgYHtyfQpjaGlsZGNhcmVfdXNlcnMgPC0gY2hpbGRjYXJlX2RhdGEgJT4lCiAgZmlsdGVyKCFpcy5uYShUT1RFWFBQUSksICFpcy5uYShCQllEQVlQUSksICFpcy5uYShJTkNMQVNTMiksIENISUxEQUdFID4gMCkgJT4lCiAgbXV0YXRlKAogICAgY2hpbGRjYXJlX3NoYXJlID0gQkJZREFZUFEgLyBUT1RFWFBQUSwKICAgIGV4cGVuZF9xdWludGlsZSA9IG50aWxlKFRPVEVYUFBRLCA1KQogICkKCmBgYApUaGVuLCBJIGNyZWF0ZWQgYSBhbm90aGVyIGRhdGFmcmFtZSBiYXNlZCBvZmYgdGhlIGNoaWxkY2FyZV91c2VycywgdGhhdCBpc29sYXRlZCBvbmx5IHRob3NlIGZhbWlsaWVzIHRoYXQgcGF5IGZvciBjaGlsZGNhcmUtIGkuZS4gbm90IHRob3NlIHdobyBnZXQgaXQgZnJlZS4gCgpgYGB7cn0KY2hpbGRjYXJlX3BheWVycyA8LSBjaGlsZGNhcmVfdXNlcnMgJT4lCiAgZmlsdGVyKEJCWURBWVBRID4gMCkKYGBgCgpOZXh0LCBJIGZvdW5kIGF2ZXJhZ2VzIGZvciBib3RoIGRhdGFmcmFtZXMsIGZvciB0aGVzZSBleHBlbmRpdHVyZXMgdG8gYmUgYWJsZSB0byBncmFwaC4KYGBge3J9CnN1bW1hcnlfdXNlcnMgPC0gY2hpbGRjYXJlX3VzZXJzICU+JQogIGdyb3VwX2J5KGV4cGVuZF9xdWludGlsZSkgJT4lCiAgc3VtbWFyaXNlKGF2Z19zaGFyZSA9IG1lYW4oY2hpbGRjYXJlX3NoYXJlLCBuYS5ybSA9IFRSVUUpKQoKc3VtbWFyeV9wYXllcnMgPC0gY2hpbGRjYXJlX3BheWVycyAlPiUKICBncm91cF9ieShleHBlbmRfcXVpbnRpbGUpICU+JQogIHN1bW1hcmlzZShhdmdfc2hhcmUgPSBtZWFuKGNoaWxkY2FyZV9zaGFyZSwgbmEucm0gPSBUUlVFKSkKYGBgCgpIZXJlLCBJIGNyZWF0ZWQgYSBjb25zaXN0ZW50IGF4aXMgZm9yIHRoZSBncmFwaHMuIApgYGB7cn0KbWF4X3NoYXJlIDwtIG1heChjKHN1bW1hcnlfdXNlcnMkYXZnX3NoYXJlLCBzdW1tYXJ5X3BheWVycyRhdmdfc2hhcmUpLCBuYS5ybSA9IFRSVUUpCgpgYGAKVGhlIGZpcnN0IHBsb3QgSSBjcmVhdGVkIGZlYXR1cmVzIGFsbCBjaGlsZGNhcmUgdXNlcnMsIHJlZ2FyZGxlc3Mgb2YgcGF5IG9yIG5vdC4gCgpgYGB7cn0KcDEgPC0gZ2dwbG90KHN1bW1hcnlfdXNlcnMsIGFlcyh4ID0gZmFjdG9yKGV4cGVuZF9xdWludGlsZSksIHkgPSBhdmdfc2hhcmUpKSArCiAgZ2VvbV9jb2woZmlsbCA9ICJwaW5rIikgKwogIGxhYnMoCiAgICB0aXRsZSA9ICJBdmVyYWdlIENoaWxkY2FyZSBTaGFyZSAoQWxsIFVzZXJzLCBJbmNsdWRpbmcgRnJlZSkiLAogICAgeCA9ICJFeHBlbmRpdHVyZSBRdWludGlsZSIsCiAgICB5ID0gIkF2ZXJhZ2UgU2hhcmUgb2YgRXhwZW5kaXR1cmVzIgogICkgKwogIHRoZW1lX21pbmltYWwoKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgbWF4X3NoYXJlKSkKCmBgYAoKVGhlIHNlY29uZCBwbG90IGhhcyBqdXN0IHRoZSBwYXllcnMuIApgYGB7cn0KcDIgPC0gZ2dwbG90KHN1bW1hcnlfcGF5ZXJzLCBhZXMoeCA9IGZhY3RvcihleHBlbmRfcXVpbnRpbGUpLCB5ID0gYXZnX3NoYXJlKSkgKwogIGdlb21fY29sKGZpbGwgPSAibGF2ZW5kZXIiKSArCiAgbGFicygKICAgIHRpdGxlID0gIkF2ZXJhZ2UgQ2hpbGRjYXJlIFNoYXJlIChTcGVuZGluZyBIb3VzZWhvbGRzIE9ubHkpIiwKICAgIHggPSAiRXhwZW5kaXR1cmUgUXVpbnRpbGUiLAogICAgeSA9ICJBdmVyYWdlIFNoYXJlIG9mIEV4cGVuZGl0dXJlcyIKICApICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIG1heF9zaGFyZSkpCgpgYGAKYGBge3J9CnByaW50KHAxICsgcDIpCmBgYAoKYGBge3J9Cmluc3RhbGwucGFja2FnZXMoImNsaXByIikKYGBgCmBgYHtyfQpsaWJyYXJ5KGNsaXByKQpsaWJyYXJ5KGtuaXRyKQoKa25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoIn4vRGVza3RvcC9DaGlsZGNhcmUtQWZmb3JkYWJpbGl0eS5wbmciKQoKYGBgCgo=