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=