Work From Home: Who Can and Who Does?

Getting Data

I combine the 2019 and 2021 datasets when creating new variables and then separate them by year again before creating the survey design object for each sample year.

ACS Survey Data Notes

IPUMS link for Survey package

Survey questions for EMPSTAT & LABFORCE:

  1. Last week, did this person work for pay at a job or business? (Yes or no) – Yes becomes coded as EMPSTAT = 1-Employed.
  2. Last week, did this person do ANY work for pay, even as little as one hour?(Yes or no) – Yes becomes coded as LABFORCE = 2-Yes in the labor force.

Survey questions for INCEARN:

  1. INCEARN = INCWAGE + INCBUS00
    • Total amount earned in last 12 months: Wages, salary, commissions, bonuses, tips. [Yes –> ______ ] is coded as INCWAGE value.

    • INCEARN includes self-employment income, INCWAGE does not.

      • INCWAGE does not include Farming income and self-employment income, but INCEARN does.

usa_00011.xml and usa_00011.dat.gz are the same as Box files named IL_2021_1yr_ACS.dat.gz and IL_2021_1yr_ACS_datDDI.xml

original xml file references the file name that it is called in the download. Either change the XML file to reference the correct .dat.gz files OR just keep track of which extracts are the same as the box file names.

# old version with less variables:
#ddi <- read_ipums_ddi("usa_00009.xml") # 45 variables
#data <- read_ipums_micro(ddi) # 126623 observations before any filtering

# larger version with 147 variables. uses same file as Box file named "IL_2021_1yr_ACS.dat.gz and IL_2021_1yr_ACS_datDDI.xml
ddi <- read_ipums_ddi("usa_00011.xml") # downloaded April 10 2023
data2021 <- read_ipums_micro(ddi) # 126623 observations before any filtering
Use of data from IPUMS USA is subject to conditions including that users should
cite the data appropriately. Use command `ipums_conditions()` for more details.
data2021 <- data2021 %>% select(YEAR, INCEARN, INCWAGE, INCTOT, TRANWORK, OCCSOC, CLASSWKR, EMPSTAT, LABFORCE, PERWT, COUNTYFIP, PUMA, PWSTATE2, AGE, STRATA, CLUSTER, RACE, HISPAN, SEX, CIHISPEED, CINETHH, MULTGEN, NCHILD, NCHLT5, MARST, FERTYR, EDUC, DEGFIELD, OCC, IND, OCC2010, METRO, CITY, HHINCOME, SERIAL,HHWT, NUMPREC, SUBSAMP,HHTYPE )

# same sample but with 150+ variables. 
# NEED TO CHANGE XML file that referneces the data file. currently says usa_00011.dat.gz so these two lines of code do not work. 

ddi <- read_ipums_ddi("C:/Users/aleaw/Box/Fiscal Futures/FY22_Working/WFH/Data/IL_2019_1yearACS_datDDI.xml") # downloaded April 10 2023
data2019 <- read_ipums_micro(ddi) # 126623 observations before any filtering
Use of data from IPUMS USA is subject to conditions including that users should
cite the data appropriately. Use command `ipums_conditions()` for more details.
data2019 <- data2019 %>% select(YEAR, INCEARN, INCWAGE, INCTOT, TRANWORK, OCCSOC, CLASSWKR, EMPSTAT, LABFORCE, PERWT, COUNTYFIP, PUMA, PWSTATE2, AGE, STRATA, CLUSTER, RACE, HISPAN, SEX, CIHISPEED, CINETHH, MULTGEN, NCHILD, NCHLT5, MARST, FERTYR, EDUC, DEGFIELD, OCC, IND, OCC2010, METRO, CITY, HHINCOME, SERIAL,HHWT, NUMPREC, SUBSAMP,HHTYPE   )

data <- rbind(data2019, data2021) #125,007 observations before any filtering. 


# replaces 0 with NA for variables listed. Allows topline to calculate "Valid Percent" when it recognizes missing values

data <- data %>% replace_with_na(replace = list(
  EMPSTAT= c(0), 
  LABFORCE=c(0), 
  CLASSWKR = c(0),
  OCCSOC = c(0),
  CIHISPEED = c(0),
  CINETHH = c(0),
  TRANWORK = c("N/A","0"))) %>% 
  filter(LABFORCE == 2 & INCEARN > 0) # in labor force and 18 years old and up abd positive earned incomes. 


data <- data %>% mutate(age_cat = 
                              case_when(AGE < 24 ~ "16to24",
                                        AGE > 24 & AGE < 35 ~ "25to34",
                                        AGE > 34 & AGE < 45 ~ "35to44",
                                        AGE > 44 & AGE < 55 ~ "45to54",
                                        AGE > 54 & AGE < 65 ~ "55to64",
                                        AGE > 64 ~ "65+"))

data <-  data %>% mutate(white = if_else(RACE ==1, 1, 0),
         black = if_else(RACE ==2, 1, 0), 
         asian = if_else(RACE %in% c(4,5,6), 1, 0),
         otherrace = if_else(RACE %in% c(3,7,8,9),1,0)) %>%
  group_by(COUNTYFIP,PUMA) %>%
  mutate(pct_white = sum(white)/n(),
         pct_black = sum(black)/n()) %>% 
  ungroup() %>%
  mutate(race_cat = case_when(
    RACE ==1~"White",
    RACE ==2 ~ "Black", 
    RACE %in% c(4,5,6)~"Asian",
    RACE %in% c(3,7,8,9)~"Other"))


## numbers used for income breaks are calculated in Income Deciles section. 
# created now so that the variable exists in the joined dataset before creating the survey design object

data <- data %>% 
  mutate(incdecile_w = case_when(
    INCEARN < 8000 ~ 1, 
    INCEARN >= 8000 & INCEARN < 18000 ~ 2,
    INCEARN >= 18000 & INCEARN < 26000 ~ 3,
    INCEARN >= 26000 & INCEARN < 35000 ~ 4,
    INCEARN >= 35000 & INCEARN < 43000 ~ 5,
    INCEARN >= 43000 & INCEARN < 54000 ~ 6,
    INCEARN >= 54000 & INCEARN < 68000 ~ 7,
    INCEARN >= 68000 & INCEARN < 85000 ~ 8,
    INCEARN >= 85000 & INCEARN < 120000 ~ 9,
    INCEARN >= 120000 ~ 10)
  ) %>%
  ## Padding FIPS code for merging with spatial geometry later
  mutate(county_pop_type = if_else(COUNTYFIP==0, 
                                   "Rural Counties", "Urban Counties")) %>%
  mutate(PUMA = str_pad(PUMA, 5, pad="0"),
         countyFIP = str_pad(COUNTYFIP, 3, pad = "0"))


data <- data %>%
  mutate(occ_2digits = substr(OCCSOC,1,2)) %>% 
  mutate(occ_2dig_labels = case_when(
 occ_2digits %in% c(11,13,19,15,17,19,21,23,25,27,29) ~ "Management, Business, Science, Arts",
 occ_2digits %in% c(31,32,33,34,35,36,37,38,39) ~ "Service Occupations",
 occ_2digits %in% c(41,42,43) ~ "Sales & Office Jobs",
occ_2digits %in% c(45,46,47,48,49 ) ~"Natural Resources, Construction",
occ_2digits %in% c(51, 52, 53) ~ "Production, Transportation",
occ_2digits == 55 ~ "Military")) 

data <- data %>%
  mutate(occ_2digits = substr(OCCSOC,1,2)) %>% 
  mutate(occ_2dig_labels_d = case_when(
 occ_2digits %in% c(11) ~ "Management",
  occ_2digits %in% c(13) ~ "Business & Finance",
  occ_2digits %in% c(15) ~ "Computer, Engineering & Science",
  occ_2digits %in% c(17) ~ "Architecture & Engineering",
  occ_2digits %in% c(19) ~ "Life/Social Sciences",
 occ_2digits == 21 ~ "Community & Social Services",
occ_2digits == 23 ~ "Legal",
occ_2digits == 25 ~ "Educational Instruction",
occ_2digits == 27 ~ "Arts, Design, Entertainainment",
occ_2digits == 29 ~ "Health Practictioners",
occ_2digits == 31 ~ "Healthcare Support",
occ_2digits == 33 ~ "Protective services",
occ_2digits == 35 ~ "Food Services",
occ_2digits == 37 ~ "Building Cleaning & Maintenance",
occ_2digits == 41 ~ "Sales",
occ_2digits == 43 ~"Office & Administration",
occ_2digits == 45 ~ "Farm, Fish, Forest",
occ_2digits == 47 ~ "Construction & Extractraction",
occ_2digits == 49 ~"Installation, Maintenance",
occ_2digits == 51 ~"Production",
occ_2digits == 53 ~ "Transportation & Material Moving",
occ_2digits == 55 ~ "Military",
TRUE~"Other") )

data <- data %>% 
  mutate(did_wfh = if_else(TRANWORK==80, 1, 0)) # 1 = wfh, 0 = did not wfh

data <- data %>% 
  mutate(
    PWSTATE2 = ifelse(PWSTATE2 == 0, NA, PWSTATE2),
    work_in_IL = ifelse(PWSTATE2 == "17", "In Illinois", "Out of IL"),
    did_wfh_labels = ifelse(did_wfh == 1, "Did WFH", "Did not WFH"),
    has_incearn = ifelse(INCEARN > 0, 1, 0), ## has earned income = 1
    has_occsoc = ifelse(OCCSOC > 0, 1, 0),# has occupation = 1
    has_incearn_labels = ifelse(INCEARN > 0, "Has EarnInc", "No IncData"), ## has earned income = 1
    has_occsoc_labels = ifelse(OCCSOC > 0, "Has Occ", "No Occ") ## OCCSOC code greater than zero coded as 1
    )

rm(ddi)
rm(data2019)
rm(data2021)

Descriptive Statistics

251630 observations originally in ACS 2021 and 2019 1-year samples.

123,753 observations after removing those not in the labor force and with earned incomes less than or equal to zero.

Note: Dropping groups of people using filter() from the sample will change the standard errors of estimates since it changes the sample size. Use the survey() or svy() command to drop subsets of people (like if we wanted to filter age groups). Google what commands to use to drop observations without impacting standard errors.

# data %>% 
#   group_by(YEAR, did_wfh) %>%
#   dplyr::summarize(weightedcount=sum(PERWT),
#                    unweightedcount = n()) %>%  #weighted
#   mutate(pct_weighted = round(weightedcount/sum(weightedcount), digits = 3),
#          pct_noweight = round(unweightedcount/sum(unweightedcount), digits = 3))

#valid percent BEFORE final filtering of observations (income greater than zero)
data %>% filter(YEAR == 2019) %>%
topline(did_wfh_labels, weight = PERWT)
data %>% filter(YEAR == 2021) %>%
topline(did_wfh_labels, weight = PERWT)

18.2% of Illinois workers worked at home. 76.3% went to work using some form of transportation, 5.5% of observations were missing values.

  • Valid percent: 19.2% of observations with responses did WFH and 80.8% of observations with responses did not WFH. This is the statistic we would use
  • Increased from 5.3% of all workers that worked from home in 2019
# bring in the teleworkable scores based on D&N's work.
telework <- read_csv("teleworkable_AWM.csv")
joined <- left_join(data, telework, by = c("OCCSOC" = "occ_codes"))

#May 22 2023, Changed 399011 occupation to 0. Was coding Nannies and Child care as teleworkable.
joined <- joined %>% mutate(teleworkable = ifelse(OCCSOC == "399011" | OCCSOC == "399010", 0, teleworkable))

#table(joined$teleworkable)
# mostly 0's and 1's.
#hist(joined$teleworkable)

joined <- joined %>% 
  mutate(CanWorkFromHome = case_when(
  teleworkable == 0 ~ "No WFH",
  teleworkable < 1 ~ "Some WFH",
  teleworkable == 1 ~ "Can WFH",
  TRUE ~ "Check Me")) %>% 
  # keeps observations that have earned income values and are in the labor force.
  filter(has_incearn == 1 & LABFORCE == 2) 


table(joined$CanWorkFromHome)

 Can WFH   No WFH Some WFH 
   41643    66111    15999 
table(joined$did_wfh, joined$YEAR)
   
     2019  2021
  0 56782 47136
  1  3197 10949

Pre 5.23.2023: 40,278 observations have occupations that indicate that they could Work from home, 67,339 responses have occupations indicating that they can not work from home, 16,136 might be able to work from home.

5.23.2023: 41,643 can wfh; 66111 no wfh possible, 15,999 some wfh

Survey Design

There are three different versions of the data: dstrata has both 2019 and 2021 data together (combined using rbind() above.) Using this combined design object makes some graphs easier, but I think it changes any standard errors used in estimate. I also made the 2019 and 2021 design strata from the the separate survey data. They all should have the same variables.

After comparing the 2021 5-year sample, it is possible to just use that 5-year sample download and use only the 2019 and 2021 years of observations. This automatically adjusts the dollar amounts to 2021 dollars. It is also possible to use Pre-COVID and post-COVID years to have even more observations. (pre-covid would be 2017,2018, and 2019, post-covid would be 2020, 2021)

Deciles were created from the strata in different ways below. Depending on age ranges kept, deciles shift slightly.

2019 Strata by itself:
4 9000 17000 25000 32000 40000 50000 63000 80000 114000 933000

2019 Strata income decile breaks (using the 2021 5-year extract):
4 9538 18016 26494 33912 42390 52988 66765 84781 121873 988757.
Already adjusted for inflation??????

  • 9000, 9400, 25000, 32000, 40000, 50000, 63000, 80000, 1140000, 949000

  • 8000, 18000, 26000, 35000, 43000, 54000, 68000, 85000, 120000


survey::svyquantile() uses the survey design to calculate deciles. These deciles that are created are slightly different than the deciles assigned using ntile(). I trust survey::svyquantile more because I know it applies the weights to observations when creating the deciles for earned income.

the ntile() decile variable is what is used to graph all decile images and for all income decile tables/calculations. Find a way to apply the summarized version of the svyquantiles as a new variable in the dstrata datasets. - Done.

incdecile_w is made using the breaks returned from the svyquantile command.

  • now use this variable in graphs? or create the summary tables using weights and then pass that to the graph commands. - done
#as_survey() from srvyr package

## both years together: calculations using this will have incorrect standard errors
# might be easier sometimes to graph together. Maybe. 
joined <- joined %>% filter(HHINCOME > 0 & HHINCOME!= 9999999 & HHINCOME != 9999998)  # 105 observations 
joined <- joined %>%
  mutate(HHincdecile_w = case_when(
    INCEARN < 34000 ~ 1,
    INCEARN >= 34000 & INCEARN < 51900 ~ 2,
    INCEARN >= 51900 & INCEARN < 68000 ~ 3,
    INCEARN >= 68000 & INCEARN < 83600 ~ 4,
    INCEARN >= 83699 & INCEARN < 100000 ~ 5,
    INCEARN >= 100000 & INCEARN < 120000 ~ 6,
    INCEARN >= 120000 & INCEARN < 142400 ~ 7,
    INCEARN >= 142400 & INCEARN < 175000 ~ 8,
    INCEARN >= 175000 & INCEARN < 235000 ~ 9,
    INCEARN >= 235000 ~ 10)
  )

dstrata <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = joined) %>% 
  as_survey() %>%
  mutate(decile = ntile(INCEARN, 10))



# 2019 data turned into survey item
dstrata2019 <- joined %>% filter(YEAR==2019) 
dstrata2019 <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, 
                                 weights = ~PERWT, data = dstrata2019) %>% 
  as_survey() %>% 
  mutate(decile = ntile(INCEARN, 10))


dstrata2021 <- joined %>% filter(YEAR==2021) 

dstrata2021 <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = dstrata2021) %>% as_survey() %>%
  mutate(decile = ntile(INCEARN, 10))

# deciles using ntile(). Not weighted!!  Close to income deciles from weighted suvey design though.

Comparison of Women w/ & w/o Kids under 5

Women under 40 who could work from home in the occupation category with large amount of people who could work from home (Management, Business, Science & Arts, all SOC 2-digit codes < 30-0000)

Under5 is binary variable: 0 means no children under 5. 1 means at least 1 or more children under 5.

318,174 women in 2019 worked from home and 1,140,835 women in 2021 worked from home.

childttest2021<-joined %>% 
  filter(YEAR == 2021)%>%
  filter(SEX == 2 & AGE < 40) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))
write.csv(childttest2021, "with_kids_comparison.csv")



childttest2019<-joined %>% 
  filter(YEAR == 2019)%>%
  filter(SEX == 2 & AGE < 40) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

kidsdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2021)

kidsdesign2 <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2019)

#withkids <- childttest %>% filter(under5 == 1)
#table(withkids$did_wfh_labels)
#nokids <- childttest %>% filter(under5==0)
#table(nokids$did_wfh_labels)


svytable(~under5+did_wfh_labels, kidsdesign) 
      did_wfh_labels
under5 Did not WFH Did WFH
     0      174904   91658
     1       49846   29442
svytable(~under5+did_wfh_labels, kidsdesign) %>% as_tibble() %>%
 #  group_by(did_wfh_labels) %>% 
     mutate(Prop = round(n/sum(n), digits =3))
svytable(~under5+did_wfh_labels, kidsdesign) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      174904   91658
     1       49846   29442

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign, statistic = "F")
F = 1.0905, ndf = 1, ddf = 3182, p-value = 0.2964
# also chi square test?
svychisq(~under5+did_wfh_labels, kidsdesign, statistic = "Chisq")

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, kidsdesign, statistic = "Chisq")
X-squared = 1.9676, df = 1, p-value = 0.2964
# t-test between with kids and without kids group. Weighted.
# t-test probably isn't right because it isn't a continuous variable.
# svyttest(under5~did_wfh, kidsdesign)


#svytable(~did_wfh_labels+YEAR+under5, design = dstrata)
svytable(~under5+did_wfh_labels, design = kidsdesign) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      174904   91658
     1       49846   29442

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign, statistic = "F")
F = 1.0905, ndf = 1, ddf = 3182, p-value = 0.2964
svytable(~under5+did_wfh_labels, design = kidsdesign2) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      253418   12702
     1       66901    6638

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign2, statistic = "F")
F = 10.485, ndf = 1, ddf = 3088, p-value = 0.001216
 #svychisq(under5~did_wfh_labels, design = kidsdesign)
#crosstab(did_wfh_labels, under5, weight = PERWT, unwt_n = TRUE, df = childttest2021)

#crosstab(did_wfh_labels,under5, weight = PERWT, unwt_n = TRUE, df = childttest2019)


### Switch variable order.
crosstab(under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest2021)
crosstab(under5,did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest2019)
#crosstab_3way(YEAR, under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest#, pct_type = "cell")

#glm(did_wfh~under5, data = childttest2021) %>% summary()
#svyglm(did_wfh~under5, design = kidsdesign) %>% summary()

For men in 2019, 7.1% of men without kids worked from home. 7.6% of men with kids worked from home.

2019:
21.8% of men who did not WFH had kid under 5.
22.8% of men who did WFH had a kid under 5.
7.2% of men who did not have kids under 5 worked from home.
7.6% of men with kids under 5 worked from home.

In 2019:
22% of women who did not WFH had a kid under 5.
24% of women who did WFH had a kid under 5.
5% of women without children under 5 worked from home.
9% of women with children under 5 worked from home.

In 2021:|
21% of women who did not WFH had a kid under 5.
34% of women who did WFH had a kid under 5.
34% of women without children under 5 worked from home.
37% of women with children under 5 worked from home.

2021:
20.4% of men who did not work from home had kids under 5.
20.45% of men who did work from home had kids under 5.
40.45% of men without kids under 5 worked from home.
40.55% of men with kids under 5 worked from home.

Not a statistically significant difference but still interesting.

For women under 45:

childttest2021<-joined %>% 
  filter(YEAR == 2021)%>%
  filter(SEX == 2 & AGE < 45) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

childttest2019<-joined %>% 
  filter(YEAR == 2019)%>%
  filter(SEX == 2 & AGE < 45) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

kidsdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2021)

#withkids <- childttest %>% filter(under5 == 1)
#table(withkids$did_wfh_labels)
#nokids <- childttest %>% filter(under5==0)
#table(nokids$did_wfh_labels)


svytable(~under5+did_wfh_labels, kidsdesign)
      did_wfh_labels
under5 Did not WFH Did WFH
     0      228825  121522
     1       57559   36530
svychisq(~under5+did_wfh_labels, kidsdesign)

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, kidsdesign)
F = 2.9369, ndf = 1, ddf = 4158, p-value = 0.08665
svyttest(under5~did_wfh, kidsdesign)

    Design-based t-test

data:  under5 ~ did_wfh
t = 1.6909, df = 3987, p-value = 0.09094
alternative hypothesis: true difference in mean is not equal to 0
95 percent confidence interval:
 -0.004807002  0.065089151
sample estimates:
difference in mean 
        0.03014107 
#svytable(~did_wfh_labels+YEAR+under5, design = dstrata)
#svytable(~under5+YEAR+did_wfh_labels, design = dstrata)


#svychisq(did_wfh_labels~under5+YEAR, design = dstrata)
#crosstab(did_wfh_labels, under5, weight = PERWT, unwt_n = TRUE, df = childttest2021)

#crosstab(did_wfh_labels,under5, weight = PERWT, unwt_n = TRUE, df = childttest2019)
#crosstab_3way(YEAR, under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest#, pct_type = "cell")

#glm(did_wfh~under5, data = childttest2021) %>% summary()

For MEN under 40:

In 2019:
20.8% who did not WFH had a kid under 5.
21.5% who did WFH had a kid under 5.

In 2021: 22% of men that did and did not WFH had a kid under 5.

childttest2021<-joined %>% 
  filter(YEAR == 2021)%>%
  filter(SEX == 1 & AGE < 40) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))
write.csv(childttest2021, "with_kids_comparison.csv")



childttest2019<-joined %>% 
  filter(YEAR == 2019)%>%
  filter(SEX == 1 & AGE < 40) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

kidsdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2021)

kidsdesign2 <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2019)

#withkids <- childttest %>% filter(under5 == 1)
#table(withkids$did_wfh_labels)
#nokids <- childttest %>% filter(under5==0)
#table(nokids$did_wfh_labels)


svytable(~under5+did_wfh_labels, kidsdesign) 
      did_wfh_labels
under5 Did not WFH Did WFH
     0      149045  101265
     1       38192   26053
svytable(~under5+did_wfh_labels, kidsdesign) %>% as_tibble() %>%
 #  group_by(did_wfh_labels) %>% 
     mutate(Prop = round(n/sum(n), digits =3))
svytable(~under5+did_wfh_labels, kidsdesign) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      149045  101265
     1       38192   26053

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign, statistic = "F")
F = 0.0012511, ndf = 1, ddf = 2729, p-value = 0.9718
# also chi square test?
svychisq(~under5+did_wfh_labels, kidsdesign, statistic = "Chisq")

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, kidsdesign, statistic = "Chisq")
X-squared = 0.001837, df = 1, p-value = 0.9718
# t-test between with kids and without kids group. Weighted.
# t-test probably isn't right because it isn't a continuous variable.
# svyttest(under5~did_wfh, kidsdesign)


#svytable(~did_wfh_labels+YEAR+under5, design = dstrata)
svytable(~under5+did_wfh_labels, design = kidsdesign) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      149045  101265
     1       38192   26053

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign, statistic = "F")
F = 0.0012511, ndf = 1, ddf = 2729, p-value = 0.9718
svytable(~under5+did_wfh_labels, design = kidsdesign2) %>% summary()
      did_wfh_labels
under5 Did not WFH Did WFH
     0      235335   18234
     1       65519    5373

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, design = kidsdesign2, statistic = "F")
F = 0.06253, ndf = 1, ddf = 2767, p-value = 0.8026
 #svychisq(under5~did_wfh_labels, design = kidsdesign)
#crosstab(did_wfh_labels, under5, weight = PERWT, unwt_n = TRUE, df = childttest2021)

#crosstab(did_wfh_labels,under5, weight = PERWT, unwt_n = TRUE, df = childttest2019)


### Switch variable order.
crosstab(under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest2021)
crosstab(under5,did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest2019)
#crosstab_3way(YEAR, under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest#, pct_type = "cell")

#glm(did_wfh~under5, data = childttest2021) %>% summary()
#svyglm(did_wfh~under5, design = kidsdesign) %>% summary()

For MEN under 45:

childttest2021<-joined %>% 
  filter(YEAR == 2021)%>%
  filter(SEX == 1 & AGE < 45) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

childttest2019<-joined %>% 
  filter(YEAR == 2019)%>%
  filter(SEX == 1 & AGE < 45) %>%
  filter(CanWorkFromHome == "Can WFH" & occ_2digits <30)  %>%  
  mutate(under5 = ifelse(NCHLT5 > 0, 1, 0))

kidsdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~PERWT, data = childttest2021)

#withkids <- childttest %>% filter(under5 == 1)
#table(withkids$did_wfh_labels)
#nokids <- childttest %>% filter(under5==0)
#table(nokids$did_wfh_labels)


svytable(~under5+did_wfh_labels, kidsdesign)
      did_wfh_labels
under5 Did not WFH Did WFH
     0      193236  126685
     1       50862   34791
svychisq(~under5+did_wfh_labels, kidsdesign)

    Pearson's X^2: Rao & Scott adjustment

data:  svychisq(~under5 + did_wfh_labels, kidsdesign)
F = 0.18489, ndf = 1, ddf = 3589, p-value = 0.6672
svyttest(under5~did_wfh, kidsdesign)

    Design-based t-test

data:  under5 ~ did_wfh
t = 0.42896, df = 3490, p-value = 0.668
alternative hypothesis: true difference in mean is not equal to 0
95 percent confidence interval:
 -0.02531256  0.03949063
sample estimates:
difference in mean 
       0.007089036 
#svytable(~did_wfh_labels+YEAR+under5, design = dstrata)
#svytable(~under5+YEAR+did_wfh_labels, design = dstrata)


#svychisq(did_wfh_labels~under5+YEAR, design = dstrata)
crosstab(did_wfh_labels, under5, weight = PERWT, unwt_n = TRUE, df = childttest2021)
crosstab(did_wfh_labels,under5, weight = PERWT, unwt_n = TRUE, df = childttest2019)
#crosstab_3way(YEAR, under5, did_wfh_labels, weight = PERWT, unwt_n = TRUE, df = childttest#, pct_type = "cell")

glm(did_wfh~under5, data = childttest2021) %>% summary()

Call:
glm(formula = did_wfh ~ under5, data = childttest2021)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-0.3924  -0.3924  -0.3838   0.6076   0.6162  

Coefficients:
             Estimate Std. Error t value Pr(>|t|)    
(Intercept)  0.392423   0.009225  42.540   <2e-16 ***
under5      -0.008596   0.018875  -0.455    0.649    
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for gaussian family taken to be 0.2380974)

    Null deviance: 874.82  on 3675  degrees of freedom
Residual deviance: 874.77  on 3674  degrees of freedom
  (103 observations deleted due to missingness)
AIC: 5160.7

Number of Fisher Scoring iterations: 2

Household data

hhbreaks2019 = (32100, 50000, 65600, 80500, 97300, 115700, 137500, 168000, 225010) and max is 1671000

hhbreaks2021 = (34000, 51900, 68000, 83600, 1e+05 120,000 142,400 175,000 235,000) and max is 1,797,000.

Code
joined <- joined %>% filter(HHINCOME > 0 & HHINCOME!= 9999999 & HHINCOME != 9999998)  # 105 observations 

joined %>%
  ggplot() + geom_histogram(aes(x=HHINCOME, weight = HHWT))

Code
joined %>% # 122000 observations 
ggplot() + geom_histogram(aes(x=HHINCOME))

Code
HHdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~HHWT, data = joined)

inc_quantiles <-survey::svyquantile(~HHINCOME, design=HHdesign, 
                    quantiles = c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1) ,
                    na.rm=TRUE, ci = FALSE  )
inc_quantiles
$HHINCOME
     0   0.1   0.2   0.3   0.4   0.5    0.6    0.7    0.8    0.9       1
[1,] 4 32900 50000 66600 82000 99000 117000 140000 171000 230000 1797000

attr(,"hasci")
[1] FALSE
attr(,"class")
[1] "newsvyquantile"
Code
# With  HH Weights:  4 32900 50000 66600 82000 99000 117000 140000 171000 230000 1797000
# With WRONG weights:  (34000, 51900, 68000, 83600, 1e+05 120,000 142,400 175,000 235,000
#Code done above when creating variables in beginning chunks.
joined <- joined %>%
  mutate(HHincdecile_w = case_when(
    INCEARN < 32900 ~ 1,
    INCEARN >= 32900 & INCEARN < 50000 ~ 2,
    INCEARN >= 50000 & INCEARN < 66600 ~ 3,
    INCEARN >= 66600 & INCEARN < 82000 ~ 4,
    INCEARN >= 82000 & INCEARN < 99000 ~ 5,
    INCEARN >= 99000 & INCEARN < 117000 ~ 6,
    INCEARN >= 117000 & INCEARN < 140000 ~ 7,
    INCEARN >= 140000 & INCEARN < 171000 ~ 8,
    INCEARN >= 171000 & INCEARN < 230000 ~ 9,
    INCEARN >= 230000 ~ 10)
  )

HHdesign <- survey::svydesign(id = ~CLUSTER, strata = ~STRATA, weights = ~HHWT, data = joined)
table <- svytable(~YEAR+HHincdecile_w+did_wfh_labels,  design = HHdesign) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR,HHincdecile_w)%>%
  mutate(Prop=round(n/sum(n), digits=3)) %>%
  filter(did_wfh_labels == "Did WFH")

table # has proportions calculated out of TOTAl for both years
Code
table %>%
  ggplot(aes(factor(HHincdecile_w, levels = c(1,2,3,4,5,6,7,8,9,10), labels = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%")), 
                     y=Prop, fill = YEAR, group = factor(YEAR, levels = "2021","2019"))) + 
  geom_col(stat="identity", position = "dodge")+
  #geom_col(stat = "identity", position = "stack") +   # scale_x_discrete(limits = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%"))+

 # facet_wrap(~YEAR)+
   coord_flip()+
    geom_text(aes(label = scales::percent(Prop, accuracy = 0.1L)), position = position_dodge(width = 0.8), hjust = 1.1,
              size = 4) + 
  labs(title ="Percent of each HOUSEHOLD income decile that did WFH",
  subtitle = "2019 vs 2021",
       caption = "ACS 1 year samples for 2019 and 2021. Working from home based on TRANWORK question on commuting and HHINCOME variable.
       All workers in the labor force, all ages included.
       Income based on HHINCOME for household income of survey respondents.", 
       x= "Income Deciles", 
       y = "Percent of workers working from home") + 
 theme(legend.position = "bottom", legend.title = element_blank())+
  theme_classic()+
    scale_fill_manual(values = c("#a6bddb", "#2b8cbe")) +
  scale_y_continuous(labels = scales::percent)

Individual Level Data

Occupations

Combined into 6 major occupation groups. Broadest categories are made up of multiple 2-digit OCCSOC codes.

Code
#table includes observations from BOTH years.
#table(joined$occ_2dig_labels, joined$did_wfh_labels)


#table(joined$occ_2digits)

crosstab_3way(joined, YEAR, occ_2dig_labels, did_wfh_labels, weight = PERWT)

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Military occupations make up less than 0.5% of the labor force and were removed from the graph. Occupation categories are based on broadest aggregated BLS categories used by the BLS.

Code
table <- svytable(~YEAR+occ_2dig_labels, design = dstrata) 
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(-n)
table

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Military occupations make up less than 0.5% of the labor force and were removed from the graph. Occupation categories are based on broadest aggregated BLS categories used by the BLS.

Code
table %>% filter(occ_2dig_labels != "Military") %>% ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels)), y=n, group = YEAR)) + 
  geom_col(stat = "identity", fill="lightblue") +
  facet_wrap(~YEAR)+
        geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.02,Prop, "")), accuracy = .1),accuracy  = .1L ),position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(
    title ="Proportion of Occupation Types in  Illinois",
    subtitle = "By Most Aggregated Occupation Groups used by BLS & ACS",
       x = "", y = "Estimated Number of Workers")+
 scale_y_continuous(labels = scales::comma)+
scale_x_discrete(labels = function(x) str_wrap(x, width=25))+ # makes labels better on axsis

  coord_flip()

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Military occupations make up less than 0.5% of the labor force and were removed from the graph. Occupation categories are based on broadest aggregated BLS categories used by the BLS.

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Military occupations make up less than 0.5% of the labor force and were removed from the graph. Occupation categories are based on broadest aggregated BLS categories used by the BLS.

### Proportion of All Workers in each Occupation Type ###
table <- svytable(~YEAR+occ_2dig_labels_d, design = dstrata) 
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(-n)
table

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Occupation categories based on first 2 digits of OCCSOC occupation codes. Labels for occupations that make up less than 2% of the workers were not labeled for legibility reasons.

table %>% ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels_d)), y=n, group = YEAR)) + 
  geom_col(stat = "identity", fill="lightblue") +
  facet_wrap(~YEAR)+
        geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.02,Prop, "")), accuracy = .1),accuracy  = .1L ),position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="WFH Feasibility by Occupation Type",
       #subtitle = "Little change between 2019 and 2021 Occurred",
       x = "", y = "Estimated Number of Workers") + scale_y_continuous(labels = scales::comma)+
  coord_flip()

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Occupation categories based on first 2 digits of OCCSOC occupation codes. Labels for occupations that make up less than 2% of the workers were not labeled for legibility reasons.
### Percent of Workersworking from home within each Broad Occupation type ###
table <- svytable(~YEAR+did_wfh_labels+occ_2dig_labels, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, occ_2dig_labels)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(did_wfh_labels, -n)
table

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Occupation categories based on first 2 digits of OCCSOC occupation codes. Labels for occupations that make up less than 2% of the workers were not labeled for legibility reasons.

table %>% filter(occ_2dig_labels != "Military" ) %>%
  ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels)), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +facet_wrap(~YEAR)+
        geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.05,Prop, "")), accuracy = .1),accuracy  = .1L ),position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Proportion of Workers in each Occupation Who Did WFH",
       subtitle = "Percentages add to 100% within each occupation",
       x = "", y = "Estimated # of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Military occupations were excluded from graph due to low occurance of observations.") + scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c("#a6bddb", "#2b8cbe")) +
  coord_flip()

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Occupation categories based on first 2 digits of OCCSOC occupation codes. Labels for occupations that make up less than 2% of the workers were not labeled for legibility reasons.
## Proportion of all workers in each occupation cateogory.## 
table <- svytable(~YEAR+did_wfh_labels+occ_2dig_labels, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(did_wfh_labels, -n)
table
table %>% 
  filter(occ_2dig_labels != "Military") %>%
  ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels)), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
  geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.02,Prop, "")), accuracy = .1), accuracy  = .1L ),
            position = position_stack(vjust=.5), size=3) +
  theme_classic() + 
  theme(legend.position = "none", legend.title = element_blank(), 
        plot.title.position = "plot",
         panel.background = element_rect(fill='transparent'), #transparent panel bg
    plot.background = element_rect(fill='transparent', color=NA) #transparent plot bg
   )+
  labs(title ="Proportion of Illinois Workforce Who Worked From Home",
      # subtitle = "All workers in labor force with occsoc codes in a year add to 100%",
       x = "", y = "Estimated Number of Workers") +#,
     # caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") 
scale_y_continuous(labels = scales::comma) +
  
    scale_x_discrete(labels = function(x) str_wrap(x, width=25))+ # makes labels better on axsis

  scale_fill_manual(values = c("#a6bddb",  "#2b8cbe")) + coord_flip()

#ggsave("Figure3.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
#ggsave("Figure3.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure3.png", limitsize = FALSE, width = 8, height = 4, units = "in")
### Detailed Occuation Types ## 
table <- svytable(~YEAR+did_wfh_labels+occ_2dig_labels_d, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(did_wfh_labels, -n)
table
table %>%ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels_d)), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.01,Prop, "")), accuracy = .1),accuracy  = .1L ),position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by 2-digit Occupation type",
       x = "", y = "Estimated Number of Workers") + 
  scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c("#a6bddb", "#2b8cbe")) +
  coord_flip()

ACS 1 year samples for 2019 and 2021 used for weighted population estimates. Graph interpretation: 3.6% of all worker in the labor force in 2021 were in Management occupations and worked from home. 8.3% of all workers were in management and did not work from home. Workers in Management occupations make up 11.9% of the entire workforce.

# Both years, detailed observation types
table <- svytable(~YEAR+CanWorkFromHome+occ_2dig_labels_d, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  arrange(CanWorkFromHome,-n) %>%
  mutate(Prop =round(n/sum(n), digits=3))
table
table %>% 
  ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels_d)), y=n, fill = CanWorkFromHome, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
  geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.01,Prop, "")), accuracy = .1), accuracy= 0.1L ),position = position_stack(vjust=.5), size=3) +
theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent of Illinois Workers that Could WFH by Occupation Type",
       x = "", y = "Estimated Number of Workers") + 
  scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c( "#117733","#44AA99","#D8D5C5")) +
  coord_flip()

OCCSOC codes and Teleworkable scores from occupation characteristics. 11.6% of all workers in Illinois had management occupations (6.6 Can WFH + 1.8 No WFH + 3.2 Some WFH in 2021). 6.6% of all workers in Illinois had management occupations and could feasibly WFH. ACS 1 year samples for 2019 and 2021 used for weighted population estimates.

table <- svytable(~YEAR+CanWorkFromHome+occ_2dig_labels_d, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  filter(YEAR==2021)%>% 
  arrange(CanWorkFromHome, -n) %>%
  mutate(Prop =round(n/sum(n), digits=3))


table %>% 
  ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels_d)), y=n, fill = CanWorkFromHome, group=YEAR)) + 
  geom_col(position="stack", stat = "identity")+
  geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.01,Prop, "")), accuracy = .1), accuracy= 0.1L ), position = position_stack(vjust=.5), size=3) +
theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent of Workers that Could Feasibily Work From Home in 2021", 
       x = "", y = "# of People",
      caption = "Occupation codes (OCCSOC)from the 2021 1-year ACS merged with work from home feasibility scores.") + scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c( "#2b8cbe","#a6bddb","gray80")) +
  coord_flip()

## Proportion of all workers in each occupation cateogory.## 
table <- svytable(~YEAR+CanWorkFromHome+occ_2dig_labels, design = dstrata) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(CanWorkFromHome, -n)
table
Figure1 <- table %>% filter(occ_2dig_labels != "Military") %>%
  ggplot(aes(x=fct_rev(fct_inorder(occ_2dig_labels)), y=n, fill = CanWorkFromHome, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
  geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.02,Prop, "")), accuracy = .1),accuracy  = .1L ), 
            position = position_stack(vjust=.5), size=2.5) +
  theme_classic() +
  theme(plot.title = element_text(hjust=0), legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Proportion of All WFH Workers by Broad Occupation",
     #  subtitle = "All workers in labor force with occsoc codes in a year add to 100%",
       x = "", y = "Number of Workers in Illinois",
   #   caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates"
     ) + 
  scale_x_discrete(labels = function(x) str_wrap(x, width=25))+ # makes labels better on axsis
  scale_y_continuous(labels = scales::comma) +
  scale_fill_manual(values = c( "#2b8cbe","#a6bddb", "gray89")) +
  coord_flip()          # = element_text(hjust = 0, vjust=2.12))

Figure1

#ggsave("Figure1.eps", limitsize = FALSE,width = 8, height = 4, units = "in")#
# ggsave("Figure1.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure1.png", limitsize = FALSE, width = 8, height = 4, units = "in")

#ggsave("Figure1.png", limitsize=FALSE, dpi = "retina")

Could WFH vs. did WFH

Code
## Totals add up to total number of workers in a year
table <- svytable(~CanWorkFromHome+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% # will divide by all workers per year
  mutate(Prop =round(n/sum(n), digits=3)) %>%
  arrange(did_wfh_labels, -n)

table

Percentages add up to 100 when adding all workers together within a year. Did work from home based on TRANWORK==80 variable from ACS surveys. Can Work from home based on teleworkable classification in Dingel & Niemen (2020). ACS 1 year samples for 2019 and 2021 used for weighted population estimates.

Code
## percentages add up to 100 when adding all workers together for a year
table %>% ggplot(aes(CanWorkFromHome, y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
  #scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "none", legend.title = element_blank())+
  labs(title ="Did those who could work from home actually work from home?",subtitle = "2019 vs 2021",
       x = "", y = "Estimated Number of Workers") + 
  scale_y_continuous(labels = scales::comma) + 
  scale_fill_manual(values = c("#a6bddb",  "#2b8cbe"))

Percentages add up to 100 when adding all workers together within a year. Did work from home based on TRANWORK==80 variable from ACS surveys. Can Work from home based on teleworkable classification in Dingel & Niemen (2020). ACS 1 year samples for 2019 and 2021 used for weighted population estimates.
Code
#ggsave("Figure1.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
#ggsave("Figure1.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure8.png", limitsize = FALSE, width = 7, height = 5, units = "in")
table <- svytable(~CanWorkFromHome+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, CanWorkFromHome)%>% # divides by all workers per year within each categor
  mutate(Prop =round(n/sum(n), digits=3)) %>% 
  arrange(did_wfh_labels,-n)
table
xtabs(~did_wfh_labels+CanWorkFromHome+YEAR, data = dstrata)
, , YEAR = 2019

              CanWorkFromHome
did_wfh_labels Can WFH No WFH Some WFH
   Did not WFH   18433  30664     7094
   Did WFH        1484    971      596

, , YEAR = 2021

              CanWorkFromHome
did_wfh_labels Can WFH No WFH Some WFH
   Did not WFH   13594  27599     5380
   Did WFH        6217   2225     2370
## percentages add up to 100 when adding all workers together for a year
table %>% ggplot(aes(fct_inorder(CanWorkFromHome), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack")  +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop, accuracy = 0.1L)), position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Did those who COULD work from home actually work from home:", subtitle = "2019 vs 2021",
       x = "", y = "# of People",
      caption = "Comparison graph that might feel more correct.
      Percentages add up to 100 when adding all workers within each CanWorkFromHome category for each a year.
      Did work from home based on TRANWORK==80 variable from ACS surveys. Can Work from home based on teleworkable classification in Dingel & Niemen (2020).
            ACS 1 year samples for 2019 and 2021 used for weighted population estimates.") + scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c("#a6bddb",  "#2b8cbe")) 

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, CanWorkFromHome)%>% # divides by all workers per year within each categor
  filter(CanWorkFromHome != "Some WFH") %>%
  mutate(Prop =round(n/sum(n), digits=3)) %>% 
  arrange(did_wfh_labels,-n)
table
xtabs(~did_wfh_labels+CanWorkFromHome+YEAR, data = dstrata)
, , YEAR = 2019

              CanWorkFromHome
did_wfh_labels Can WFH No WFH Some WFH
   Did not WFH   18433  30664     7094
   Did WFH        1484    971      596

, , YEAR = 2021

              CanWorkFromHome
did_wfh_labels Can WFH No WFH Some WFH
   Did not WFH   13594  27599     5380
   Did WFH        6217   2225     2370
## percentages add up to 100 when adding all workers together for a year
table %>% ggplot(aes(fct_inorder(CanWorkFromHome), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack")  +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop, accuracy = 0.1L)), position = position_stack(vjust=.5), size=3) +
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Did those who COULD work from home actually work from home:", subtitle = "2019 vs 2021",
       x = "", y = "# of People",
      caption = "Comparison graph that might feel more correct.
      Percentages add up to 100 when adding all workers within each CanWorkFromHome category for each a year.
      Did work from home based on TRANWORK==80 variable from ACS surveys. Can Work from home based on teleworkable classification in Dingel & Niemen (2020).
            ACS 1 year samples for 2019 and 2021 used for weighted population estimates.") + scale_y_continuous(labels = scales::comma)+
  scale_fill_manual(values = c("#a6bddb",  "#2b8cbe")) 

# 
# table <- svytable(~CanWorkFromHome+YEAR+did_wfh_labels, design = dstrata) 
# # proportion of each respondant's sex and if they worked from home for each year in sample
# table <- table %>% 
#   as_tibble() %>% 
#   group_by(YEAR, did_wfh_labels)%>% # divides by all workers per year within each categor
#   mutate(Prop =round(n/sum(n), digits=3))


## percentages add up to 100 when adding all workers together for a year
## Don't like this version of the graph ### 
# table %>% ggplot(aes(did_wfh_labels, y=n, fill = CanWorkFromHome, group = YEAR)) + 
#   geom_col(stat = "identity", position = "stack") +
#   facet_wrap(~YEAR)+
#     geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
#   theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
#   labs(title ="Did those who COULD work from home actually work from home:", subtitle = "2019 vs 2021",
#        x = "", y = "# of People",
#       caption = "Comparison graph that might feel more correct.
#       Percentages add up to 100 when adding all workers within each did_wfh category for each a year.
#       Did work from home based on TRANWORK==80 variable from ACS surveys. Can Work from home based on teleworkable classification in Dingel & Niemen (2020).
#             ACS 1 year samples for 2019 and 2021 used for weighted population estimates.") + scale_y_continuous(labels = scales::comma)

Ideally switch order of categories so that Did WFH is on the bottom of stack. Allows easier visual comparison.

Creating Income Deciles

# svyquantile shows the breaks for the quantiles. hypothetically uses weights of observations for calculation of deciles.
# equal number of people should be in each decile after weights are applied 
inc_quantiles <- survey::svyquantile(~INCEARN, design=dstrata2019, 
    quantiles = c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1) , na.rm=TRUE,  ci = FALSE  )
# $INCEARN for 2019
#[1,] 4 8000 16000 24000 30900 40000 50000 62000 80000 113000 933000
# values not adjusted to 2021 values.
inc_quantiles
$INCEARN
     0  0.1   0.2   0.3   0.4   0.5   0.6   0.7   0.8    0.9      1
[1,] 4 8300 16500 25000 31200 40000 50000 62000 80000 114000 933000

attr(,"hasci")
[1] FALSE
attr(,"class")
[1] "newsvyquantile"
inc_quantiles <-survey::svyquantile(~INCEARN, design=dstrata2021, 
                    quantiles = c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1) ,
                    na.rm=TRUE, ci = FALSE  )
inc_quantiles
$INCEARN
     0  0.1   0.2   0.3   0.4   0.5   0.6   0.7   0.8    0.9      1
[1,] 4 8000 17000 25600 35000 42500 53000 68000 85000 120000 949000

attr(,"hasci")
[1] FALSE
attr(,"class")
[1] "newsvyquantile"
# $INCEARN
# [1,] 4 7200 16000 25000 34000 42000 52000 67000 85000 120000 949000



breaks2019 <- c(7200, 16000, 25000, 34000, 42000, 52000, 67000, 85000, 120000)

breaks2019adjusted <- c(8478, 16956, 25434, 32853, 42390, 52988, 65705, 84781, 120813) 
# from 2021 5 year sample and filtered for just 2019. 
# already adjusted for inflation.
# included for comparison and to decide to use 5 year ACS or 2019 and 2021 1 year ACS

breaks2021 <- c(8000, 18000, 26000, 35000, 43000, 54000, 68000, 85000, 120000)

# Code done above when creating variables in beginning chunks. 
# joined <- joined %>% 
#   mutate(incdecile_w = case_when(
#     INCEARN < 8000 ~ 1, 
#     INCEARN >= 8000 & INCEARN < 18000 ~ 2,
#     INCEARN >= 18000 & INCEARN < 26000 ~ 3,
#     INCEARN >= 26000 & INCEARN < 35000 ~ 4,
#     INCEARN >= 35000 & INCEARN < 43000 ~ 5,
#     INCEARN >= 43000 & INCEARN < 54000 ~ 6,
#     INCEARN >= 54000 & INCEARN < 68000 ~ 7,
#     INCEARN >= 68000 & INCEARN < 85000 ~ 8,
#     INCEARN >= 85000 & INCEARN < 120000 ~ 9,
#     INCEARN >= 120000 ~ 10)
#   )
# number of observations in each decile after weights used for creating the income deciles
#table(joined$incdecile_w)

# no major differnce between years in who COULD work from home based on teleworkable codes. Makes sense. 
# ggplot(joined, aes(teleworkable, weight = PERWT)) +
# geom_histogram()+facet_wrap(~YEAR)



table <- svytable(~YEAR+incdecile_w+did_wfh_labels,  design = dstrata) # proportion of each respondants sex in sample

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR,incdecile_w)%>%
  mutate(Prop=round(n/sum(n), digits=3)) %>%
  filter(did_wfh_labels == "Did WFH")

table # has proportions calculated out of TOTAl for both years
table %>%
  ggplot(aes(factor(incdecile_w, levels = c(1,2,3,4,5,6,7,8,9,10), labels = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%")), 
                     y=Prop, fill = YEAR, group = factor(YEAR, levels = "2021","2019"))) + 
  geom_col(stat="identity", position = "dodge")+
  #geom_col(stat = "identity", position = "stack") +   # scale_x_discrete(limits = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%"))+

 # facet_wrap(~YEAR)+
   coord_flip()+
    geom_text(aes(label = scales::percent(Prop, accuracy = 0.1L)), position = position_dodge(width = 0.8), hjust = 1.1,
              size = 4) + 
  labs(title ="Working From Home by Earned Income Deciles",
  subtitle = "2019 vs 2021",
 #      caption = "ACS 1 year samples for 2019 and 2021. Working from home based on TRANWORK question on commuting.
#       All workers in the labor force, all ages included.
#       Income based on INCEARN for total earned income of survey respondents.", 
       x= "Income Deciles", 
       y = "Percent of earners working from home") + 
 theme(legend.position = "none", legend.title = element_blank())+
  theme_classic()+
    scale_fill_manual(values = c("#a6bddb", "#2b8cbe")) +
  scale_y_continuous(labels = scales::percent)

#ggsave("Figure6.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
#ggsave("Figure6.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure6.png", limitsize = FALSE, width = 8, height = 4, units = "in")

decile_labels <- c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%")

who did work from home in lower income brackets???

  • 399011 in Service Occupations had 148 observations, 311122 had 86.

  • Vast Majority of those that did work form home in the bottom 10% of earners had management, business, sales, or office jobs. (specifically 399011, 253041,436014)

  • outliers: occupation 537062, 533030, 537065 in production and transportation, 399011 in service occupations which usually need to be in person.

  • 399011 (2nd and 3rd decile), 311122 (2nd and 3rd decile)

data %>% filter(did_wfh==1 & incdecile_w < 4) %>% group_by(incdecile_w, occ_2digits, occ_2dig_labels, OCCSOC) %>% summarize(obs = n()) %>% arrange(incdecile_w,-obs)

Gender and Working from home

19.2% of those in the labor force worked from home in 2021.

  • 10.7% were women, 9.8% were men.
  • In 2021, 17.6% of male workers did WFH and 21% of female workers did WFH.

52.5% of those in the labor force that have occupation codes were Men, 47.5% were Women.

#round(prop.table(svytable(~did_wfh_labels, design=dstrata2019))*100,digits=2) 
#94.7 did not wfh, 5.29 did work from home in 2019

round(prop.table(svytable(~did_wfh_labels, design=dstrata2021))*100,digits=2) 
did_wfh_labels
Did not WFH     Did WFH 
      80.76       19.24 
# # unweighted attempt at summary table using "data" dataframe
# table <- data %>% 
#  # filter(did_wfh==1) %>%  
#   mutate(total = n())  %>%
#   group_by(YEAR, did_wfh_labels, SEX) %>% 
#   dplyr::summarize(n_unweighted=n()) %>% 
#   mutate(Prop = n_unweighted/sum(n_unweighted))
# # unweighted sex proportions each year
# # for comparison
# 
# # of those that did work from home,51% were female in 2019 and 51.9% were female in 2021. 
# table 

table <- svytable(~SEX+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each sex that did or did not work from home 
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, SEX)%>% 
  mutate(Prop =round(n/sum(n), digits=4))
# 5.4% of women worked at home in 2019 and 21% of women worked at home in 2021.
table
# # attempt 1, not what I wanted
# table %>% ggplot(aes(did_wfh_labels, y=Prop, group = YEAR, fill = YEAR)) + 
#   geom_col(stat = "identity", position = "dodge") +    
#   geom_text(aes(label = scales::percent(Prop)), position = position_dodge(width = .9), size=3,vjust=1.1) + 
#   theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
#   labs(title ="First Attempt at WFH graph for each Year",
#        x = "", y = "",
#       caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::percent)


# # attempt 2
# table %>% ggplot(aes(factor(SEX, labels = c("Male", "Female")), y=Prop, fill = did_wfh_labels, group = YEAR)) + 
#   geom_col(stat = "identity", position = "stack") +
#   facet_wrap(~YEAR)+
#     geom_text(aes(label = scales::percent(Prop)), position = position_fill(vjust=.5), size=3) + 
#   theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
#   scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
#   labs(title ="Percent working from home by Sex: 2019 vs 2021",
#        x = "", y = "",
#       caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::percent)


### Percentages add up to 100% for each gender for each year. 
table %>% ggplot(aes(factor(SEX, labels = c("Male", "Female")), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
  scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by Sex: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::comma)

#compare combined strata survey design to single year survey objects:
# MATCHES
# table <- svytable(~SEX+did_wfh, design = dstrata2019) # proportion of each respondants sex in sample
# table <- table %>% 
#   as_tibble() %>% 
#   group_by(SEX) %>%
#   mutate(Prop = round(n/sum(n), digits=4))
# table
# 
# table <- svytable(~SEX+did_wfh, design = dstrata2021, 
#                   round= TRUE) 
# table <- table %>% 
#   as_tibble() %>% group_by(SEX) %>%
#   mutate(Prop = round(n/sum(n), digits=4))
# table



## Totals add up to total number of workers in a year
table <- svytable(~SEX+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% # grouped by Year and Sex!!
  mutate(Prop =round(n/sum(n), digits=4))
table
## percentages add up to 100 when adding all workers together for a year
table %>% ggplot(aes(factor(SEX, labels = c("Male", "Female")), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
  scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by Sex: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates.
      Percentages add up to 100 when adding all workers together each year.
      Working from home based on TRANWORK==80 variable from ACS surveys.") + scale_y_continuous(labels = scales::comma)

svyttest(formula = SEX~did_wfh_labels, design = dstrata2021)

    Design-based t-test

data:  SEX ~ did_wfh_labels
t = 8.3, df = 35419, p-value < 2.2e-16
alternative hypothesis: true difference in mean is not equal to 0
95 percent confidence interval:
 0.04071947 0.06589675
sample estimates:
difference in mean 
        0.05330811 
svychisq(~did_wfh_labels+SEX, dstrata2021, statistic = "Chisq")

    Pearson's X^2: Rao & Scott adjustment

data:  NextMethod()
X-squared = 106.93, df = 1, p-value < 2.2e-16
round(prop.table(svytable(~SEX+did_wfh_labels, design=dstrata2021))*100,digits=2)
   did_wfh_labels
SEX Did not WFH Did WFH
  1       43.21    9.27
  2       37.55    9.97
round(prop.table(svytable(~has_occsoc+SEX, design=dstrata2019))*100,digits=2)
          SEX
has_occsoc     1     2
         1 51.89 48.11
# slight drop in women in the workforce (technically women with occupations). 
round(prop.table(svytable(~has_occsoc+SEX, design=dstrata2021))*100,digits=2)
          SEX
has_occsoc     1     2
         1 52.45 47.55
CrossTable(data$SEX, data$YEAR)

 
   Cell Contents
|-------------------------|
|                       N |
| Chi-square contribution |
|           N / Row Total |
|           N / Col Total |
|         N / Table Total |
|-------------------------|

 
Total Observations in Table:  123753 

 
             | data$YEAR 
    data$SEX |      2019 |      2021 | Row Total | 
-------------|-----------|-----------|-----------|
           1 |     32427 |     31944 |     64371 | 
             |     0.264 |     0.270 |           | 
             |     0.504 |     0.496 |     0.520 | 
             |     0.519 |     0.522 |           | 
             |     0.262 |     0.258 |           | 
-------------|-----------|-----------|-----------|
           2 |     30092 |     29290 |     59382 | 
             |     0.286 |     0.292 |           | 
             |     0.507 |     0.493 |     0.480 | 
             |     0.481 |     0.478 |           | 
             |     0.243 |     0.237 |           | 
-------------|-----------|-----------|-----------|
Column Total |     62519 |     61234 |    123753 | 
             |     0.505 |     0.495 |           | 
-------------|-----------|-----------|-----------|

 
xtabs(~SEX+YEAR, data = data) %>% summary()
Call: xtabs(formula = ~SEX + YEAR, data = data)
Number of cases in table: 123753 
Number of factors: 2 
Test for independence of all factors:
    Chisq = 1.113, df = 1, p-value = 0.2914
xtabs(~did_wfh+SEX+YEAR, data = data) %>% summary()
Call: xtabs(formula = ~did_wfh + SEX + YEAR, data = data)
Number of cases in table: 118064 
Number of factors: 3 
Test for independence of all factors:
    Chisq = 5246, df = 4, p-value = 0
## Most interesting change: 
round(prop.table(svytable(~SEX+did_wfh_labels, design=dstrata2019))*100,digits=2) 
   did_wfh_labels
SEX Did not WFH Did WFH
  1       49.27    2.58
  2       45.57    2.58
# 1 is Male, 2 is female
round(prop.table(svytable(~SEX+did_wfh_labels, design=dstrata2021))*100,digits=2) 
   did_wfh_labels
SEX Did not WFH Did WFH
  1       43.21    9.27
  2       37.55    9.97
# Chi square goodness of fit

# practice test to see if sex is 52% male and 48% female. For both years. 
chisq.test(table(joined$SEX), p = c(52, 48)/100)

    Chi-squared test for given probabilities

data:  table(joined$SEX)
X-squared = 0.0049174, df = 1, p-value = 0.9441
# can't reject the null, so the sample represents the population if the known population is 52% male and 48% female.

svytotal(x = ~interaction(SEX, did_wfh_labels), design = dstrata2021, na.rm=TRUE)
                                                total      SE
interaction(SEX, did_wfh_labels)1.Did not WFH 2562380 20128.2
interaction(SEX, did_wfh_labels)2.Did not WFH 2226558 18405.0
interaction(SEX, did_wfh_labels)1.Did WFH      549602  9349.2
interaction(SEX, did_wfh_labels)2.Did WFH      591233  9978.3
svytotal(x = ~interaction(SEX, did_wfh_labels), design = dstrata2019, na.rm=TRUE)
                                                total      SE
interaction(SEX, did_wfh_labels)1.Did not WFH 3039231 21479.7
interaction(SEX, did_wfh_labels)2.Did not WFH 2811408 21035.5
interaction(SEX, did_wfh_labels)1.Did WFH      159128  5711.1
interaction(SEX, did_wfh_labels)2.Did WFH      159046  5242.4
#svymean(x = ~interaction(INCEARN, EMPSTAT), design = dstrata2021, na.rm=TRUE)
#svymean(x = ~interaction(INCEARN, LABFORCE), design = dstrata2021, na.rm=TRUE)


svyttest(formula = INCEARN~SEX, design = dstrata2021)

    Design-based t-test

data:  INCEARN ~ SEX
t = -32.274, df = 36475, p-value < 2.2e-16
alternative hypothesis: true difference in mean is not equal to 0
95 percent confidence interval:
 -23794.51 -21069.87
sample estimates:
difference in mean 
         -22432.19 
svyttest(formula = INCEARN~did_wfh_labels, design = dstrata2021)

    Design-based t-test

data:  INCEARN ~ did_wfh_labels
t = 27.63, df = 35419, p-value < 2.2e-16
alternative hypothesis: true difference in mean is not equal to 0
95 percent confidence interval:
 32054.25 36949.32
sample estimates:
difference in mean 
          34501.79 
table <- svytable(~SEX+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, SEX)%>% # grouped by Year and Sex!!
  mutate(Prop =round(n/sum(n), digits=4))
table

Null hypothesis: There is no difference in working from home associated with sex.

Alt. Hyp: Working from home is associated with sex.

svychisq(~SEX+did_wfh_labels, design = dstrata2021, statistic = "Chisq")

    Pearson's X^2: Rao & Scott adjustment

data:  NextMethod()
X-squared = 106.93, df = 1, p-value < 2.2e-16
incomebysex<- dstrata2021 %>% 
  mutate(INCEARN = as.numeric(INCEARN) )%>%
  svyby(formula = ~ INCEARN, by = ~SEX, 
      FUN = svyquantile, 
      na.rm=TRUE,
        quantiles  = c(0,0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9) )

incomebysex %>% 
  pivot_longer(cols = c(-SEX),names_to = "columns", values_to = "values") %>% 
  mutate(values = round(values, digits =2))
output <- svyby(formula = ~INCEARN, by = ~SEX, design = dstrata2021,
      FUN = svymean, na.rm=TRUE)
  
out_col <- mutate(output, 
                  lower = INCEARN - 2*se, 
                  upper = INCEARN + 2*se)

ggplot(out_col, aes(SEX, INCEARN, ymin=lower, ymax=upper)) + geom_col() +geom_errorbar(width = 0.7) + labs( y = "Average Earned Income", x = "Sex")+ scale_x_discrete(limits = c("Male", "Female") )

table <- svytable(~SEX+NCHLT5+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each sex that did or did not work from home 
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, did_wfh_labels)%>% 
  mutate(Prop =round(n/sum(n), digits=4))
# 5.4% of women worked at home in 2019 and 21% of women worked at home in 2021.
table

Graphing Income Deciles

percent includes both years for combined strata.

Code
table <- svytable(~YEAR+incdecile_w+CanWorkFromHome,  design = dstrata) # proportion of each respondants sex in sample

table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, incdecile_w)%>%
  mutate(Prop=round(n/sum(n), digits=3)) %>%
  mutate(CanWorkFromHome = factor(CanWorkFromHome, levels = c('No WFH', 'Some WFH',  'Can WFH')))

table 
Code
table[rev(order(table$CanWorkFromHome)),]%>%
  ggplot(aes(factor(incdecile_w, levels = c(1,2,3,4,5,6,7,8,9,10), 
                    labels = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%")), 
                     y=Prop, 
            # fill = CanWorkFromHome,
            fill = factor(CanWorkFromHome, levels = c("No WFH", "Some WFH",  "Can WFH")), 
             group = factor(YEAR, levels = "2021","2019"))) + 
  geom_col(aes(fill = factor(CanWorkFromHome, levels = c("No WFH", "Some WFH",  "Can WFH")),stat="identity", position = "stack"))+
   coord_flip()+

    geom_text(aes(label = scales::percent(Prop, accuracy = 0.1L)), position = position_fill(vjust =.5), size = 2) + 
    guides(fill = guide_legend(reverse = TRUE))+

  labs(title ="Percent of each income decile that could potentially work from home",
       subtitle = "2019 vs 2021",
       caption = " Based on occupation codes from ACS 1 year samples for 2019 and 2021. Teleworkable coding based on Dingel & Neimen 2020.
       All workers in the labor force, all ages included.
       Income based on INCEARN for total earned income of survey respondents.", 
       x= "Income Deciles", 
       y = "Percent of workers that can work from home based on occupation characteristics") +   theme_classic()+

 theme(legend.position = "bottom", legend.title = element_blank())+
  scale_y_continuous(labels = scales::percent) +   facet_wrap(~YEAR)

Code
# summary(as.numeric(data$INCEARN))
# 
# # using decile made # of observations
# summary <- dstrata %>% 
#   group_by(YEAR,decile) %>% 
#   summarize(min = min(INCEARN),
#             max=max(INCEARN),
#             avg_income = mean(INCEARN),
#             average_income = survey_mean(INCEARN),
#             pop_represented = sum(PERWT),
#             obs_count = n())
# summary %>% 
#   ggplot(aes(x=decile, y=average_income, label=scales::dollar(average_income))) + 
#   geom_col()+
#   scale_x_discrete(limits = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%"))+
#   scale_y_continuous(labels = scales::dollar)+labs(x="",y="", title = "Average earned income for each income decile")+
#   geom_text(vjust = -0.5, size = 3)+
#   facet_wrap(~YEAR)
# 
# 
# 
# # with weighted deciles made from # of pop represented
# summary <- dstrata %>% 
#   group_by(YEAR, incdecile_w) %>% 
#   summarize(min = min(INCEARN),
#             max=max(INCEARN),
#             avg_income = mean(INCEARN),
#             average_income = survey_mean(INCEARN),
#             pop_represented = sum(PERWT),
#             obs_count = n())
# 
# summary %>% 
#   ggplot(aes(x=incdecile_w, y=average_income, label=scales::dollar(average_income))) + 
#   geom_col()+
#   scale_x_discrete(limits = c("Bottom 10%", "20%", "30%", "40%", "50%", "60%", "70%", "80%", "90%", "Top 10%"))+
#   scale_y_continuous(labels = scales::dollar)+labs(x="",y="", title = "Average earned income for each income decile")+
#   geom_text(vjust = -0.5, size = 3)+
#   facet_wrap(~YEAR)




output <- svyby(formula = ~INCEARN, by = ~YEAR+incdecile_w, design = dstrata, 
      FUN = svymean, na.rm=TRUE)
  
out_col <- mutate(output, 
                  lower = INCEARN - 2*se, 
                  upper = INCEARN + 2*se)

ggplot(out_col, aes(incdecile_w, INCEARN, ymin=lower, ymax=upper)) + 
  geom_col(stat = "identity") +
  geom_errorbar(width = 0.7) + 
  facet_wrap(~YEAR) + 
  labs(title = "Average income earned for each decile of income earners", y = "Average Earned Income for each Income Decile", x = "Deciles of Income Earners", caption = "NOT adjusted for inflation")+ coord_flip() +
  scale_x_discrete(limits = decile_labels ) + 
 # ylim(0,250000)+
  scale_y_continuous(label = scales::dollar, limits = c(0,275000))+
   geom_text(aes(label = scales::dollar(INCEARN)), size=3, hjust=-.3)

# data has 2019 and 2021 observatins TOGETHER
topline(data, did_wfh,  weight=PERWT)
# All members of the labor force could have said they either work from home (TRANWORK=80), go to work using some form of transportation, or didn't answer the question. 8.2% of the labor force did not answer the TRANWORK question and should not be included in calculations.
data %>% filter(YEAR == 2021) %>% crosstab(x=RACE, y=did_wfh_labels, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)  # matches Francis Total Row in Race output
data  %>% crosstab_3way(x=YEAR, y=did_wfh, z=race_cat, weight = PERWT)
crosstab(data, x=LABFORCE, y=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE) # matches Francis, 52% male, 48% female in laborforce
data %>% filter(YEAR ==2021) %>% crosstab(x=did_wfh_labels, y=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)
crosstab_3way(data, x=YEAR, y=did_wfh_labels, z=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)
crosstab(joined, x=LABFORCE, y=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE) # matches Francis, 52% male, 48% female in laborforce
joined %>% filter(YEAR ==2021) %>% crosstab(x=did_wfh_labels, y=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)
crosstab_3way(joined, x=YEAR, y=did_wfh_labels, z=SEX, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)
# Employment Status
table(data$EMPSTAT) # unweighted

data %>% 
  group_by(YEAR, as_factor(EMPSTAT)) %>%
  dplyr::summarize(weightedcount=sum(PERWT),
                   unweightedcount = n()) %>%  #weighted
  mutate(pct_weight = weightedcount/sum(weightedcount),
         pct_noweight = unweightedcount/sum(unweightedcount))

# Labor Force
data %>% 
  group_by(YEAR, as_factor(LABFORCE)) %>%
  dplyr::summarize(weightedcount=sum(PERWT),
                   unweightedcount = n()) %>%  #weighted
  mutate(pct_weight = weightedcount/sum(weightedcount),
         pct_noweight = unweightedcount/sum(unweightedcount))


# Class of Worker
data %>% 
  group_by(YEAR, as_factor(CLASSWKR)) %>%
  dplyr::summarize(weightedcount=sum(PERWT),
                   unweightedcount = n()) %>%  #weighted
  mutate(pct_weight = weightedcount/sum(weightedcount),
         pct_noweight = unweightedcount/sum(unweightedcount))

Unweighted -

EMPSTAT: 59,259 observations are employed, 4,194 unemployed observations, and 41,289 observations are not in the workforce (21,881 NAs)

LABFORCE: 63,453 are in labor force, 41,289 are not. (21,881 NAs)

CLASSWKR: Of these, 68,388 work for wages and 7183 people are self-employed. (51,052 NA)

did_wfh: 10,949 observations worked from home, 47,584 did not work from home. Based on TRANWORK variable: recoded as binary variable (either did wfh or did not wfh).

Weighted -

EMPSTAT: 6,102,522 people are employed (49%), 479,879 people are unemployed (3.8%), and 3,624,811 are not in the labor force (29%). There are 2,463,257 missing values; Same as LABFORCE.

LABFORCE: 6,582,401 people (52%) are in the labor force. 3,625,811 (28%) of people are not in the labor force. 2,463,257 (20%) of observations missing values.

  • employed and unemployed equal number of people in labor force - that’s good

did_wfh: 19.2% did work from home and 80.8% did not work from home in Illinois (when not filtering for age or employment)

Location of primary workplace: 5.8 million people located in Illinois.

For the counties that can be identified in the data (populations > 100,000 & < 200,000. 1-Year ACS have minimum of 65,000 population), the census summary tables are close but not identical to the tables calculated with the ACS sample data. “In this way more densely populated areas, like Chicago and Cook County will contain many PUMAs within their boundaries, while multiple sparsely populated entire counties, e.g., Jackson, Perry, Franklin, and Williamson, will comprise one PUMA.” - IPUMS v other Geographies

19 is Champaign, 31 is Cook, 37 is DeKalb, 43 is DuPage, 89 is Kane, 111 is McHenry, etc.

Economic Characteristics summary table: link

joined %>% 
  filter(CanWorkFromHome == "Some WFH") %>% 
  distinct(OCCSOC)

Race

Good example of graphing survey data. Make a summary table that has the WEIGHTED Freq and Prop of the variables of interest before passing it to graphing commands. Using svytable to make the weighted table.

Code
table <- svytable(~race_cat+YEAR+did_wfh_labels, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, race_cat)%>% # grouped by Year and Sex!!
  mutate(Prop =round(n/sum(n), digits=4)) %>%
  arrange(did_wfh_labels, -n)
table
Code
table %>% ggplot(aes(race_cat, y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
 # scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by race: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") +    scale_fill_manual(values = c("#a6bddb", "#2b8cbe")) +
 scale_y_continuous(labels = scales::comma)

Code
table <- svytable(~did_wfh_labels+YEAR+race_cat, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, did_wfh_labels)%>% # grouped by Year and Sex!!
  mutate(Prop =round(n/sum(n), digits=4))
table
Code
table %>% ggplot(aes(did_wfh_labels, y=n, fill = race_cat, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
 # scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by race: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::comma)

Code
table <- svytable(~did_wfh_labels+YEAR+race_cat, design = dstrata) 
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% # grouped by Year and Sex!!
  mutate(Prop =round(n/sum(n), digits=4))

table %>% ggplot(aes(did_wfh_labels, y=n, fill = race_cat, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) +
 # scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home by race: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::comma)

Code
svyby(~did_wfh, by = ~RACE, design = dstrata2021, svymean, na.rm=TRUE)
Code
svyby(~INCEARN, by = ~RACE, design = dstrata2021, FUN = svymean, na.rm=TRUE)
Code
joined %>% crosstab_3way(x=YEAR, y=did_wfh, z=white, weight = PERWT)
Code
joined %>% crosstab_3way(x=YEAR, y=did_wfh, z=RACE, weight = PERWT)
Code
# joined %>% crosstab_3way(x=YEAR, y=did_wfh, z=white, weight = PERWT) %>% 
#   ggplot(aes(x=`1`, y=YEAR, fill = factor(white))) + 
#   geom_col(stat="identity", position = "fill") + labs(title = "Percent of White people that were able to work at home each year")
# 
# joined %>% crosstab_3way(x=YEAR, y=did_wfh, z=black, weight = PERWT) %>% 
#   ggplot(aes(x=`1`, y=YEAR, fill = factor(black))) + 
#   geom_col(stat="identity", position = "fill") + labs( "Percent of Black People that were able to work at home each year")


crosstab(joined, x=RACE, y=did_wfh, weight = PERWT, unwt_n=TRUE, n=FALSE)
Code
crosstab(joined, x=RACE, y=did_wfh, weight = PERWT, pct_type = "column", unwt_n=TRUE, n=FALSE)
Code
crosstab(joined, x=did_wfh, y=RACE, weight = PERWT, pct_type = "row", unwt_n=TRUE, n=FALSE)
Code
crosstab(joined, x=did_wfh, y=RACE, weight = PERWT)
Code
joined %>% filter(YEAR == 2021) %>%
  group_by(RACE) %>%
  summarize(Freq = n()) %>%
  mutate(Prop = Freq/sum(Freq))
Code
svytable(~RACE, design=dstrata2021) %>% 
  as.data.frame() %>% # creates a frequency count by default?
  mutate(Prop =Freq/sum(Freq))
Code
topline(dstrata2019, RACE, weight = PERWT)
Code
topline(dstrata2021, RACE, weight = PERWT)
Code
#svytotal(x = ~interaction(RACE, did_wfh_labels), design = dstrata2021, na.rm=TRUE)

# need to create race variables before the dstrata survey object.
#svytotal(x = ~interaction(white, did_wfh_labels), design = dstrata2021, na.rm=TRUE)


Age

table(joined$AGE,joined$LABFORCE)

joined%>% filter(YEAR == 2021 & AGE>64 & INCEARN > 0) %>% summary()
# more then 75% of those under 18 make less than $5,000 a year.Not the kind of workers we are interested in anyways.  

# Even more extreme for less than 17

table(joined$age_cat, joined$did_wfh_labels)

Internet Access

Other variables: CIHISPEED, CINETHH, MULTGEN, NCHILD, NCHLT5, MARST, FERTYR

  • CINETHH reports whether any member of the household accesses the Internet. Here, “access” refers to whether or not someone in the household uses or connects to the Internet, regardless of whether or not they pay for the service.

  • CIHISPEED reports whether the respondent or any member of their household subscribed to the Internet using broadband (high speed) Internet service such as cable, fiber optic, or DSL service.

#10 is yes, 20 is no access. 00 is NA
table <- svytable(~CIHISPEED +did_wfh_labels+YEAR, design = dstrata) 
topline(dstrata2019, CIHISPEED, weight = PERWT)
topline(dstrata2021, CIHISPEED, weight = PERWT)
table
, , YEAR = 2019

         did_wfh_labels
CIHISPEED Did not WFH Did WFH
       10     4613288  277027
       20      878321   29514

, , YEAR = 2021

         did_wfh_labels
CIHISPEED Did not WFH Did WFH
       10     3871147 1027194
       20      683274   82666
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR, CIHISPEED)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>% 
  arrange(did_wfh_labels, -n)
table
table %>% ggplot(aes(factor(CIHISPEED, labels = c("Has high speed", "No high speed")), y=Prop, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_fill(vjust=.5), size=3) + 
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home & Access to high speed Internet: 2019 vs 2021",
       x = "", y = "",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::percent) +scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))

table %>% ggplot(aes(factor(CIHISPEED, labels = c("Has high speed", "No high speed")), y=n, fill = did_wfh_labels, group = YEAR)) + 
  geom_col(stat = "identity", position = "stack") +
  facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) + 
  theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home & Access to high speed Internet: 2019 vs 2021",
       x = "", y = "",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") +scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))

### Access to any type of internet ####
table <- #dstrata %>% factor(CIHISPEED,)
  svytable(~CINETHH+did_wfh_labels+YEAR, design = dstrata) 
table
, , YEAR = 2019

       did_wfh_labels
CINETHH Did not WFH Did WFH
      1     5491609  306541
      2      109151    3768
      3      249879    7865

, , YEAR = 2021

       did_wfh_labels
CINETHH Did not WFH Did WFH
      1     4554421 1109860
      2       94608   19191
      3      139909   11784
# proportion of each respondant's sex and if they worked from home for each year in sample
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3))%>% 
  arrange(did_wfh_labels, -n)
table
table %>% #filter(YEAR == 2021) %>%
  ggplot(aes(factor(CINETHH, labels = c("Has Own Access", "Has Other Access", "No Access")), y=n, fill = did_wfh_labels,
                     group = YEAR
                     )) + 
  geom_col(stat = "identity", position = "stack") +
 facet_wrap(~YEAR)+
  geom_text(aes(label = scales::percent(as.numeric(ifelse(Prop>0.05,Prop, "")), accuracy = .1),accuracy  = .1L ),position = position_stack(vjust=.5), size=3) +
  theme_classic() + 
  theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home & Access to Internet: 2019 vs 2021",
       x = "", y = "# of people",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::comma)+coord_flip() + scale_fill_manual(values = c("#a6bddb", "#2b8cbe"))+
   annotate("text", label = "< 3% of labor force", x = 2, y =1400000, size = 3, colour = "black")  + annotate("text", label = "< 5% of labor force", x = 3, y =1400000, size = 3, colour = "black")

table %>% #filter(YEAR == 2021) %>%
  ggplot(aes(did_wfh_labels, y=n, fill = factor(CINETHH, labels = c("Has Own Access", "Has Other Access", "No Access")),
                     group = YEAR
                     )) + 
  geom_col(stat = "identity", position = "stack") +
 facet_wrap(~YEAR)+
    geom_text(aes(label = scales::percent(Prop)), position = position_stack(vjust=.5), size=3) + 
  theme_classic() + 
  theme(legend.position = "bottom", legend.title = element_blank())+
  labs(title ="Percent working from home & Access to Internet: 2019 vs 2021",
       x = "", y = "# of People",
      caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::comma)+coord_flip()

# table %>% ggplot(aes(factor(CINETHH, labels = c("Has Own Access", "Has Other Access", "No Access")), y=Prop, fill = did_wfh_labels, group = YEAR)) + 
#   geom_col(stat = "identity", position = "fill") +
#   facet_wrap(~YEAR)+
#     geom_text(aes(label = scales::percent(Prop)), position = position_fill(vjust=.5), size=3) + 
#   theme_classic() + theme(legend.position = "bottom", legend.title = element_blank())+
#   labs(title ="Percent working from home & Access to Internet: 2019 vs 2021",
#        x = "", y = "",
#       caption = "ACS 1 year samples for 2019 and 2021 used for weighted population estimates,") + scale_y_continuous(labels = scales::percent)


# Access at home AND access to high speed internet.
table <- 
  svytable(~CIHISPEED+ CINETHH+did_wfh_labels+YEAR, design = dstrata) 
table
, , did_wfh_labels = Did not WFH, YEAR = 2019

         CINETHH
CIHISPEED       1
       10 4613288
       20  878321

, , did_wfh_labels = Did WFH, YEAR = 2019

         CINETHH
CIHISPEED       1
       10  277027
       20   29514

, , did_wfh_labels = Did not WFH, YEAR = 2021

         CINETHH
CIHISPEED       1
       10 3871147
       20  683274

, , did_wfh_labels = Did WFH, YEAR = 2021

         CINETHH
CIHISPEED       1
       10 1027194
       20   82666
table <- table %>% 
  as_tibble() %>% 
  group_by(YEAR)%>% 
  mutate(Prop =round(n/sum(n), digits=3)) %>% 
  arrange(YEAR, did_wfh_labels)
table
crosstab_3way(joined, YEAR, CIHISPEED, CINETHH, weight = PERWT, unwt_n = TRUE)

In 2019, an estimated 277,000 people worked from home and had highspeed internet and 29,500 did not have high speed internet .

In 2021, an estimated1,027,000 people worked from home and had high speed internet and 83,000 did not have high speed internet.

  • There is a chance that people realized that their internet was not as fast as they thought it was when they had multiple people using the internet at the same time during COVID-19.
table(joined$NCHILD)

    0     1     2     3     4     5     6     7     8     9 
70975 21828 19138  7485  1986   463   119    35    17    17 
table(joined$NCHLT5)

     0      1      2      3      4      5 
108636   9881   3201    327     16      2 

Geographic Data

table(data$PWSTATE2)

     1      2      4      5      6      8      9     11     12     13     17 
     5      1      8      2     36      5      2      6     26     18 113836 
    18     19     20     21     22     24     25     26     27     28     29 
   676    952      6    112      9      6     12     45     13      4   1443 
    30     31     33     34     36     37     39     40     41     42     45 
     2     14      2     12     26      7     26      1      2     17      7 
    46     47     48     49     51     53     54     55     56     72     81 
     2     14     42      3     11      5      3    610      5      1      2 
    82     83     85     86     88 
     5     13      4      2      3 
svytable(~did_wfh_labels+YEAR+work_in_IL, design = dstrata) 
, , work_in_IL = In Illinois

              YEAR
did_wfh_labels    2019    2021
   Did not WFH 5632943 4604673
   Did WFH      318174 1140835

, , work_in_IL = Out of IL

              YEAR
did_wfh_labels    2019    2021
   Did not WFH  217696  184265
   Did WFH           0       0
318174/ (318174+5632943) # percent of remote workers that worked outside of IL but lived in IL in 2019
[1] 0.05346458
1140835/(1140835+4604673) # 2021 percent of WFH workers that worked outside of IL
[1] 0.1985612
svytable(~has_incearn_labels+YEAR+work_in_IL, design = dstrata) 
, , work_in_IL = In Illinois

                  YEAR
has_incearn_labels    2019    2021
       Has EarnInc 5951117 5745508

, , work_in_IL = Out of IL

                  YEAR
has_incearn_labels    2019    2021
       Has EarnInc  217696  184265
svytable(~work_in_IL+YEAR+has_incearn_labels, design = dstrata) 
, , has_incearn_labels = Has EarnInc

             YEAR
work_in_IL       2019    2021
  In Illinois 5951117 5745508
  Out of IL    217696  184265
490937  / (490937  +5951117 ) # percent of remote workers that worked outside of IL but lived in IL in 2019
[1] 0.07620815
525507/(525507+5745508) # 2021 percent of WFH workers that worked outside of IL
[1] 0.08379935

7.6% of workers that earned income worked outside of IL in 2019.

8.4% of workers did so in 2021.

joined %>% 
  group_by(YEAR, county_pop_type )%>% 
  summarize(avg_teleworkable = mean(teleworkable, weight = PERWT),
                                                         
            avg_did_WFH = mean(did_wfh, na.rm=TRUE, weight = PERWT))

PUMA Level

PUMAs contain around 100,000 people.

For the counties that can be identified in the data (populations > 100,000 & < 200,000. 1-Year ACS have minimum of 65,000 population), the census summary tables are close but not identical to the tables calculated with the ACS sample data. “In this way more densely populated areas, like Chicago and Cook County will contain many PUMAs within their boundaries, while multiple sparsely populated entire counties, e.g., Jackson, Perry, Franklin, and Williamson, will comprise one PUMA.” - IPUMS v other Geographies

obs_perPUMA<- joined %>% 
   group_by(PUMA, YEAR) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n()) %>%
  arrange(unweightedcount)
### Minimimum observations are 271 in PUMA area 03528
obs_perPUMA
joined %>% 
   group_by(county_pop_type, YEAR, did_wfh_labels) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n()) %>% 
   mutate(pct_weight = weightedcount/sum(weightedcount), 
          pct_noweight = unweightedcount/sum(unweightedcount)) %>% arrange(unweightedcount)

Economic Characteristics summary table: link

# PUMA shapefiles
pumasIL <- pumas("IL", cb=T, year=2019)

#pumasIL %>% select(PUMACE10, GEOID10, NAME10) %>% write_csv("PUMAsIL.csv")
#county shapefiles
countyIL <- counties("IL", cb=T, year=2019)

#pumasdf <- fortify(pumasIL, region = 'PUMACE10')

Did WFH

# first attempt to graph data. Does appear to match the 2nd attempt below.
# mapPUMAboth <- joined %>% 
#   filter(did_wfh_labels != "NA" )%>% # create percentages withing missing values included. aka valid percent.
#    group_by(county_pop_type, YEAR, PUMA, did_wfh_labels) %>% 
#    dplyr::summarize(weightedcount=sum(PERWT), #weighted 
#                     unweightedcount = n()) %>% 
#    mutate(pct_weight = weightedcount/sum(weightedcount), 
#           pct_noweight = unweightedcount/sum(unweightedcount))%>%
#   full_join(pumasIL, by = c("PUMA" = "PUMACE10")) 
# mapPUMAboth
# 
# mapPUMAboth %>%
#   filter(did_wfh_labels != "Did not WFH") %>%
#   ggplot(aes(fill = pct_weight)) +
#   geom_sf(aes(geometry = geometry), color = "black")+ 
#   labs(title = "Percent of PUMA area population that did work from home in 2021", 
#        subtitle = "Each PUMA has >100K & < 200K people", 
#        caption = "Facet_wrapped by year") + 
#   facet_wrap(~YEAR)


mapPUMAboth <- svytable(~YEAR+PUMA+did_wfh_labels, design = dstrata)
mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH") %>%
     full_join(pumasIL, by = c("PUMA" = "PUMACE10"))
 
mapPUMAboth %>% select(YEAR, PUMA, Prop, n, NAME10)

The did_WFH variable is based on TRANWORK==80 from ACS 2019 & 2021 1-Year Survey individual level data. Each geographic region has between 100K and 200K people.

mapPUMAboth %>% 
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Where Did People Work from Home?", 
      # subtitle = "Percent of PUMA population in 2019 & 2021 that did WFH"
      ) +
  theme_classic() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank())+
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 6,
                        name = "Percent of Workers", label = scales::percent)+
  
   # geom_sf(data = countyIL, fill=NA, color="dark gray") +
  facet_wrap(~YEAR) 

The did_WFH variable is based on TRANWORK==80 from ACS 2019 & 2021 1-Year Survey individual level data. Each geographic region has between 100K and 200K people.
#ggsave("Figure5a.eps", limitsize = FALSE,width = 8, height = 5, units = "in")
#ggsave("Figure5a.pdf", limitsize = FALSE,width = 8, height = 5, units = "in")
ggsave("Figure5a.png", limitsize = FALSE, width = 8, height = 5, units = "in")
mapPUMAboth <- svytable(~YEAR+PUMA+did_wfh_labels, design = dstrata)

mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH") %>%
  pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
    mutate(pct_change= `2021`-`2019`) %>%
       full_join(pumasIL, by = c("PUMA" = "PUMACE10"))%>%
  arrange(-pct_change)
mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH") %>%
  pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
    mutate(pct_change= `2021`-`2019`) %>%
       full_join(pumasIL, by = c("PUMA" = "PUMACE10")) %>%

  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Change in Population that Did Work from Home", 
       subtitle = "2019 vs 2021", 
       caption = 
         "The did_WFH variable based on TRANWORK==80 from
         ACS 2019 & 2021 1-Year Survey individual level data. 
       Each geographic region has between 100K and 200K people. ") +
  theme_classic() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank())+
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 6,
                        name = "% change in WFH", label = scales::percent)

# as a dot graph ## 
mapPUMAboth <- svytable(~YEAR+PUMA+did_wfh_labels, design = dstrata)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH") %>%
     full_join(pumasIL, by = c("PUMA" = "PUMACE10"))

order <- mapPUMAboth %>% as_tibble() %>%
 filter(YEAR == 2021  & did_wfh_labels == "Did WFH") %>% 
    filter(Prop > 0.25 | Prop < 0.1) %>%
  select(NAME10, Prop_2021 = Prop)

mapPUMAboth <- inner_join(mapPUMAboth, order) %>% filter()


mapPUMAboth %>%
  filter(did_wfh_labels == "Did WFH" #& NAME10 != "NA" & YEAR != "NA"
         )%>% 
  filter(Prop > 0.25 | Prop < 0.1) %>%
  ggplot(aes(x = Prop*100, y= reorder(PUMA, Prop_2021*100)))+
  geom_line(aes(group = PUMA))+
  theme_classic()+
   geom_point(aes(color=YEAR), size = 3) +
      scale_color_brewer(palette="Paired", labels = c("% WFH in 2019", "% WFH in 2021"), direction = 1)+
  labs(title = "Change in County Labor Force that did WFH",
       subtitle = "Percent of Labor Force within PUMA that Did Work from Home", 
#  caption = "Graph includes PUMAs with Proportions of WFH Workers greater 
#  than 25% or less than 10%. Filtered PUMAs to increase legibility. 
#  DuPage had around 8% of the labor force working from home in 2019 and 
#  around 27% of its labor force working from home in 2021. 
#       There was ~20 percentage point increase between 2019 and 2021 for DuPage County. 
#  Working from home is based on TRANWORK variable from ACS 1-year surveys.", 
x = "Percentage Points", y = "" 
)

Graph includes PUMAs with Proportions of WFH Workers greater than 25% or less than 10%. Filtered PUMAs to increase legibility. DuPage had around 8% of the labor force working from home in 2019 and around 27% of its labor force working from home in 2021. There was ~20 percentage point increase between 2019 and 2021 for DuPage County. Working from home is based on TRANWORK variable from ACS 1-year surveys.
mapPUMAboth %>% 
  ungroup() %>%
  filter(#did_wfh_labels == "Did WFH" #& NAME10 != "NA" & YEAR != "NA"
         )%>% 
 # filter(YEAR == 2021 & (Prop > 0.25 | Prop < 0.1) ) %>%
  select(NAME10, PUMA, Prop) %>% 
  distinct() %>% arrange(desc(Prop))

Graph includes PUMAs with Proportions of WFH Workers greater than 25% or less than 10%. Filtered PUMAs to increase legibility. DuPage had around 8% of the labor force working from home in 2019 and around 27% of its labor force working from home in 2021. There was ~20 percentage point increase between 2019 and 2021 for DuPage County. Working from home is based on TRANWORK variable from ACS 1-year surveys.

Closeup of counties around Cook:

closeupFIPs<- c("097", "111", "089","043", "197", "031"#,"093"
             #   ,"007"
                )



mapPUMAboth <- svytable(~YEAR+countyFIP+PUMA+
                          did_wfh_labels, design = dstrata)

mapPUMAboth <- mapPUMAboth %>% 
  as_tibble() %>%
  filter(countyFIP %in% closeupFIPs) %>%

  group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH" & n != "0") %>%
     inner_join(pumasIL, by = c("PUMA" = "PUMACE10"))
 
mapPUMAboth %>% select(YEAR, countyFIP, PUMA, Prop, n, NAME10)
#mapPUMAboth %>%   
countyborders<- countyIL %>% 
  filter(COUNTYFP %in% closeupFIPs)
countyborders
figure5b <- ggplot(mapPUMAboth, aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
 # labs(title = "Where Did People Work from Home?: Close up View", 
  #     subtitle = "Percent of PUMA population in 2019 & 2021 that did WFH") +
  theme_classic() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank())+
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 6,
                        name = "% that did WFH", label = scales::percent)+
  facet_wrap(~YEAR) 

figure5b

figure5b <- ggplot(mapPUMAboth, aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")

figure5b +
  geom_sf(data = countyborders, fill=NA, color="black", lwd = 1) + theme_classic()+  
  theme(axis.ticks = element_blank(), axis.text = element_blank())+ facet_wrap(~YEAR)

#ggsave("Figure5b.eps", limitsize = FALSE,width = 8, height = 5, units = "in")
#ggsave("Figure5b.pdf", limitsize = FALSE,width = 8, height = 5, units = "in")
ggsave("Figure5b.png", limitsize = FALSE, width = 8, height = 5, units = "in")
mapPUMAboth <- svytable(~YEAR+PUMA+countyFIP+did_wfh_labels, design = dstrata)

mapPUMAboth %>% as_tibble() %>%
    filter(countyFIP %in% closeupFIPs) %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH" & n != "0") %>%
  pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
    mutate(pct_change= `2021`-`2019`) %>%
       inner_join(pumasIL, by = c("PUMA" = "PUMACE10")) %>%

  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Change in Population that Did Work from Home", 
       subtitle = "2019 vs 2021") +
  theme_classic() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank())+
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 6,
                        name = "% change in WFH", label = scales::percent) 

# as a dot graph ## 
mapPUMAboth <- svytable(~YEAR+PUMA+countyFIP+did_wfh_labels, design = dstrata)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>% 
  filter(countyFIP %in% closeupFIPs)%>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(did_wfh_labels == "Did WFH" & n != "0") %>%
     inner_join(pumasIL, by = c("PUMA" = "PUMACE10")) 

order <- mapPUMAboth %>% as_tibble() %>%
 filter(YEAR == 2021  & did_wfh_labels == "Did WFH") %>% 
    filter(Prop > 0.25 | Prop < 0.1) %>%
  select(NAME10, Prop_2021 = Prop)

mapPUMAboth <- inner_join(mapPUMAboth, order) %>% filter()


mapPUMAboth %>%
  filter(did_wfh_labels == "Did WFH" #& NAME10 != "NA" & YEAR != "NA"
         )%>% 
  filter(Prop > 0.25 | Prop < 0.1) %>%
  ggplot(aes(x = Prop*100, y= reorder(PUMA, Prop_2021*100)))+
  geom_line(aes(group = PUMA))+
  theme_classic()+
   geom_point(aes(color=YEAR), size = 3) +
      scale_color_brewer(palette="Paired", labels = c("% WFH in 2019", "% WFH in 2021"), direction = 1)+
  labs(title = "Change in PUMA Labor Force that did WFH",
       subtitle = "Percent of County Population that Did Work from Home", 
  caption = "", x = "Percentage Points", y = "" )

WFH Feasibility

We compute these shares using our O*NET-derived classification of occupations that can be done at home and the occupational composition using ACS responses in each PUMA by 6-digit SOC in the BLS’s 2018 Occupational Employment Statistics.

mapPUMAboth <- svytable(~YEAR+PUMA+CanWorkFromHome, design = dstrata)
mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     filter(CanWorkFromHome == "Can WFH") %>%
     full_join(pumasIL, by = c("PUMA" = "PUMACE10"))
 
mapPUMAboth %>%
ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry=geometry), color = "black")+ 


  labs(title = "Percent of PUMA area population that COULD work from home", 
       subtitle = " based on occupation characteristics: 2019 vs 2021", 
       caption = "Teleworkability based on D&N 2020 methodology. 
       OCCSOC codes from ACS 1 year Survey data at individual level.") +
  theme_classic() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank())+
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 5,
                        name = "% Potentially Could WFH", label = scales::percent) +
  geom_sf(data = countyIL, fill=NA, color = "gray")+ 

  facet_wrap(~YEAR)

Figure2b <- mapPUMAboth %>%
filter(YEAR == 2021)%>%  
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  # labs(title = "Work from Home Feasibility Rate", 
  #      subtitle = " Based on Occupation Characteristics", 
  #      caption = "Teleworkability based on D&N 2020 methodology. 
  #      OCCSOC codes from ACS 1 year Survey data at individual level.") +
  theme_void() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank(),   
        plot.title = element_text(hjust = 0.5), plot.caption = element_text(hjust=.5),  plot.subtitle = element_text(hjust = 0.5)) +
   scale_fill_gradientn(colors = c("white", "darkblue"), 
                       limits = c(0,.6),
                       n = 5,
                        name = "Labor force with\nWFH Feasibility", label = scales::percent)
Figure2b

#ggsave(Figure2b, "Figure2b.png", width=3, height=3, units = "in")

Internet Access

Make a subset of dstrata that only includes people who answered the TRANWORK/ did_WFH questions.

#transub<- subset(dstrata,TRANWORK(x=80))
Code
## CINETHH is for access to internet 
# (either at home, somewhere else, or no access)
# from joined dataframe. Not using survey objects or survey package
mapPUMAboth <- joined %>% 
   group_by(YEAR, PUMA, CINETHH) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n()) %>% 
   mutate(pct_weight = weightedcount/sum(weightedcount), 
          pct_noweight = unweightedcount/sum(unweightedcount))%>%
  full_join(pumasIL, by = c("PUMA" = "PUMACE10")) 
mapPUMAboth
Code
## identical to graph below made using svytable()
# mapPUMAboth %>%
#   filter(CINETHH ==3) %>% 
#   ggplot(aes(fill = pct_weight)) +
#   geom_sf(aes(geometry = geometry), color = "black")+ 
#     scale_fill_continuous(low = "gray", high = "red", name = "% of Population", label = scales::percent)+
#     theme_minimal()+
#     theme(legend.title = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position="right")+
#   labs(title = "Percent of population that did NOT have access to Internet", 
#        subtitle = "Geography = PUMAs", 
#        ) +   theme(legend.title = element_blank())+
#  scale_fill_gradientn(colors = c("white", "red4"), 
#                     #   limits = c(-.1,.1),
#                        n = 7,
#                         name = "Change in Access", label = scales::percent)+
#   facet_wrap(~YEAR)



## Access internet using survey objects
mapPUMAboth <- svytable(~YEAR+PUMA+CINETHH, design = HHdesign)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%   
     full_join(pumasIL, by = c("PUMA" = "PUMACE10"))

mapPUMAboth %>%
  filter(CINETHH == 3 ) %>% 
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+   
  scale_fill_continuous(low = "white", high = "red4", name = "% of Population", label = scales::percent)+
  labs(title = "Percent of population that lacked access to Internet", 
       caption = "Geography = PUMAs. Includes all dstrata responses for CINETHH.
       Does not subset for people who answered the commuting or occsoc questions.") + 
  facet_wrap(~YEAR) +  theme_minimal()+
    theme(legend.title = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position="right")

Code
# mapPUMAboth %>%   
#   select(YEAR,Prop,CINETHH,geometry) %>%
#   filter(CINETHH ==3) %>% 
#   pivot_wider( names_from ="YEAR", values_from = "Prop") %>%
#   mutate(pct_change = `2021`-`2019`) %>%
#   ggplot(aes(fill = pct_change)) +
#   geom_sf(aes(geometry = geometry), color = "black")+ 
#   theme_minimal()+
#     theme(legend.title = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position="right")+
#                            scale_fill_gradientn(colors = c("green4", "white", "red4"), 
#                        limits = c(-.15,.15),
#                        n = 7,
#                         name = "Change in Access", label = scales::percent)+
#   labs(title = "Decrease in Lack of Internet Access", 
#        subtitle = "Needs to be flipped so not double negative",
#        caption = "Rural areas were more likely to increase their access to internet at home. 
#        Change in Percentage points = 2021 % - 2019 %.
#        Access to internet at home or another location is considered having Access to internet")

mapPUMAboth %>%   
  filter(CINETHH ==1) %>% 
  pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
  mutate(pct_change = `2021`-`2019`) %>%
  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  theme_minimal()+
    theme(legend.title = element_blank(), axis.text.x = element_blank(), axis.text.y = element_blank(), panel.grid.major = element_blank(), panel.grid.minor = element_blank(), legend.position="right")+
                           scale_fill_gradientn(colors = c("red4", "white", "forestgreen"), 
                       limits = c(-.15,.15),
                       n = 7,
                        name = "Chance in Access", label = scales::percent)+
  labs(title = "Change in Labor Force with Internet at home",
       subtitle = "2019 to 2021") 

High Speed Internet

High speed internet is not the best measurement of due to them including DSL in their definition of “high speed.”

FCC standards say minimum 25Mbps for download and 3Mbps for upload. “traditionally, the way to determine if a connection is high speed is to test its ability to connect multiple devices that allow streaming and access to modern applications at the same time.

High speed internet allows teleworkers the ability to live and work in locations of their choosing without commuting to work. Also important for education, especially during COVID and online classes. Many families did not have the bandwidth necessary to support someone working from home and having children in online classes at the same time (let alone multiple children in online classes).

The Infrastructure Investment and Jobs Act (IIJA) defines “underserved” broadband as an Internet speed < 100 Mbps downstream and 20Mbps upstream.

Zoom needs between 2 and 3 Mbps for group video calls that look good.

1.0 Mbps to 1.5 Mbps for lower quality video calls that should still work.

Source

For areas that had a decrease in access to high speed internet: Is it possible that they realized that their internet sucked when multiple people tried to use it? Most people didn’t know internet speeds before the pandemic. They thought they had high speed internet precovid and then when multiple people were at home, they realized they didn’t have enough bandwith for their internet demand?

Code
### Access to Hi speed internet ###

# from joined dataframe. Not using survey objects or survey package
mapPUMAboth <- joined %>% 
   group_by(county_pop_type, YEAR, PUMA, CIHISPEED) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n()) %>% 
   mutate(pct_weight = weightedcount/sum(weightedcount), 
          pct_noweight = unweightedcount/sum(unweightedcount))%>%
  full_join(pumasIL, by = c("PUMA" = "PUMACE10")) 
mapPUMAboth
Code
## Access to Hi speed internet using survey objects
mapPUMAboth <- svytable(~YEAR+PUMA+CIHISPEED, design = HHdesign)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, PUMA) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
     full_join(pumasIL, by = c("PUMA" = "PUMACE10"))

mapPUMAboth %>%
  filter(CIHISPEED == 10) %>% 
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Percent of population WITH High Speed Internet", 
       subtitle = "", caption = "Each PUMA has >100K & < 200K people.") + 
  facet_wrap(~YEAR)+
 scale_fill_gradientn(colors = c("white", "forestgreen"), 
                       n = 5,
                        name = "Population %", label = scales::percent)+Alea_theme()

Code
mapPUMAboth %>% pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
  mutate(pct_change = `2021`-`2019`) %>%
  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Change in Access to High Speed Internet",
       subcaption = "2019 to 2021",
       caption = "Percentage point change:
       2021 PUMA% with CIHISPEED=10 - 2019 PUMA% 
       for ACS variable CIHISPEED=10.") +
  scale_fill_gradientn(colors = c("forestgreen",  "white", "red4"), 
                       n = 5,
                        name = "Change in Access", label = scales::percent) + Alea_theme()

County Level

19 is Champaign, 31 is Cook, 37 is DeKalb, 43 is DuPage, 89 is Kane, 111 is McHenry, etc.

Internet Access

### Access to Hi speed internet ###

# from joined dataframe. Not using survey objects or survey package
# mapPUMAboth <- joined %>% 
#    group_by(YEAR, countyFIP, CINETHH) %>% 
#    dplyr::summarize(weightedcount=sum(PERWT), #weighted 
#                     unweightedcount = n()) %>% 
#    mutate(pct_weight = weightedcount/sum(weightedcount), 
#           pct_noweight = unweightedcount/sum(unweightedcount))%>%   
#   filter(CINETHH ==3) %>% 
#   full_join(countyIL, by = c("countyFIP" = "COUNTYFP")) 
# mapPUMAboth
# 
# mapPUMAboth %>%
#   ggplot(aes(fill = pct_weight)) +
#   geom_sf(aes(geometry = geometry), color = "black")+ 
#   labs(title = "Percent of population that did NOT have access to Internet", 
#        subtitle = "Geography = County", 
#        ) +  
#   Alea_theme() +theme(legend.title = element_blank())+
#   scale_fill_gradientn(colors = c( "white", "red4"), 
#                        n = 5,
#                         name = "Population %", label = scales::percent)+facet_wrap(~YEAR)





## Access to High speed internet using survey objects
mapPUMAboth <- svytable(~YEAR+countyFIP+CIHISPEED, design = HHdesign)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, countyFIP) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
    filter(CIHISPEED != 20 ) %>% 
     full_join(countyIL, by = c("countyFIP" = "COUNTYFP"))

mapPUMAboth %>%
  filter(CIHISPEED == 10) %>%
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Percent of population with High-speed Internet", 
   #    subtitle = "Geograph = Counties with More than 60,000 People"
       ) + 
  facet_wrap(~YEAR)+
 scale_fill_gradientn(colors = c( "white", "green4"), 
                       n = 5,
                        name = "Percent of Population", label = scales::percent)+ Alea_theme()

mapPUMAboth %>% pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
  mutate(pct_change = `2021`-`2019`) %>%
  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black") + 
  theme_void()+ 
   scale_fill_gradientn(colors = c("red4", "white", "forestgreen"), 
                       n = 7,
                       limits = c(-.2,.2),
                        name = "Percent of Population", label = scales::percent)#+labs(title = "Change in access to High Speed Internet")

ggsave("Figure7b.png", limitsize = FALSE, width = 5, height = 4, units = "in")

#ggsave("Figure7b.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
#ggsave("Figure7b.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")


# as a bar graph ## 
mapPUMAboth %>%
  filter(YEAR==2021) %>%
ggplot(aes(group = countyFIP)) +
  geom_bar(aes(y = Prop, x= reorder(NAME, Prop)), stat = "identity") +
  #Alea_theme() + 
  labs(title = "Proportion with High Speed Internet", subtitle = "In 2021", x = "", y = "" )+
  coord_flip()

# as a dot graph ## 

order <- mapPUMAboth %>% as_tibble() %>%
 filter(YEAR == 2019 & NAME != "NA" & CIHISPEED == "10") %>% 
  select(NAME, Prop_2019= Prop)

mapPUMAboth <- left_join(mapPUMAboth, order)

mapPUMAboth %>%
  filter(NAME != "NA" & YEAR != "NA")%>%
  ggplot(aes(x = Prop, y= reorder(NAME, Prop_2019)))+
  geom_line(aes(group = NAME))+
   geom_point(aes(color=YEAR), size = 3) +
  theme_minimal() + 
  theme(legend.position = "none", legend.title = element_blank(),
               plot.title.position = "plot",
     #   panel.background = element_rect(fill='transparent'), #transparent panel bg
    plot.background = element_rect(fill='transparent', color=NA) #transparent plot bg
   )+
        scale_color_brewer(palette="Paired", labels = c("2019", "2021"), direction = 1)+

  labs(title = "Change in Access to High-speed Internet", x = "", y = "" ) +
  scale_x_continuous(label = scales::percent)

ggsave("Figure7.png", limitsize = FALSE, width = 5, height = 4, units = "in")

#ggsave("Figure7.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
#ggsave("Figure7.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")

Did work from home

mapPUMAboth <- svytable(~did_wfh_labels+YEAR+countyFIP, design = dstrata)

mapPUMAboth <- mapPUMAboth %>% as_tibble() %>%
   group_by(YEAR, countyFIP) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
  full_join(countyIL, by = c("countyFIP" = "COUNTYFP"))

mapPUMAboth %>%
      filter(did_wfh_labels == "Did WFH") %>%

  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Percent of Labor  Force that Worked from Home", 
       caption = "Geography = Counties with populations > ~60K") + 
  facet_wrap(~YEAR)  +
 scale_fill_gradientn(colors = c( "white", "darkblue"), na.value = "gray",
                       n = 5,
                        name = "Population %", label = scales::percent) + Alea_theme()

mapPUMAboth %>% pivot_wider(id_cols = -c(n), names_from ="YEAR", values_from = "Prop") %>%
  mutate(pct_change = `2021`-`2019`) %>%
  ggplot(aes(fill = pct_change)) +
  geom_sf(aes(geometry = geometry), color = "black")+ Alea_theme()+ 
   scale_fill_gradientn(colors = c( "white", "darkblue"), 
                       n = 5,
                       limits = c(0,.20),
                        name = "Percentage Point\nIncrease", label = scales::percent)#+

 # labs(title = "Percentage Point Change in Labor Force that Did WFH")

ggsave("Figure4b.eps", limitsize = FALSE, width = 8, height = 5, units = "in")
ggsave("Figure4b.pdf", limitsize = FALSE,width = 8, height = 5, units = "in")
ggsave("Figure4b.png", limitsize = FALSE, width = 8, height = 5, units = "in")




# as a dot graph ## 
order <- mapPUMAboth %>% as_tibble() %>%
 filter(YEAR == 2021 & did_wfh_labels == "Did WFH") %>% 
  select(countyFIP, Prop_2021 = Prop)

mapPUMAboth <- left_join(mapPUMAboth, order)


mapPUMAboth %>%
  filter(did_wfh_labels == "Did WFH" & NAME != "NA" & YEAR != "NA")%>%
  ggplot(aes(x = Prop*100, y= reorder(NAME, Prop_2021*100)))+
  geom_line(aes(group = NAME))+
  theme_classic()+
   geom_point(aes(color=YEAR), size = 3) +
      scale_color_brewer(palette="Paired",
                         # labels = c("% WFH in 2019", "% WFH in 2021"), 
                         direction = 1)+
  labs(title = "Change in County Labor Force that did WFH",
#  caption = "DuPage had around 8% of the labor force working from home in 2019 and 
#  around 27% of its labor force working from home in 2021. 
#       There was ~20 percentage point increase between 2019 and 2021 for DuPage County. 
#  Working from home is based on TRANWORK variable from ACS 1-year surveys.", 
x = "Labor force that WFH (%)", 
y = "" 
)#+  scale_x_continuous(label = scales::percent)

ggsave("Figure4a.eps", limitsize = FALSE,width = 8, height = 5, units = "in")
ggsave("Figure4a.pdf", limitsize = FALSE,width = 8, height = 5, units = "in")
ggsave("Figure4a.png", limitsize = FALSE, width = 8, height = 5, units = "in")

Could work from home

Based on Dingel & Niemen paper. A person’s occupation indicates the likelihood of if they could work from home.

# teleworkable is numeric
# CanWorkFromHome is categorical variable with 3 options. 


mapdataboth <- joined %>% 
  filter(CanWorkFromHome != "NA" )%>% # create percentages withing missing values included. aka valid percent.
   group_by(county_pop_type, YEAR, countyFIP, CanWorkFromHome) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n()
                    ) %>% 
   mutate(pct_weight = weightedcount/sum(weightedcount), 
          pct_noweight = unweightedcount/sum(unweightedcount))%>%
  full_join(countyIL, by = c("countyFIP" = "COUNTYFP")) # %>%
    #mutate(pct_weight = ifelse(is.na(county_pop_type), 0.04486351, pct_weight))%>%
 #  mutate(pct_weight = ifelse(is.na(county_pop_type), 0.09237573, pct_weight))# %>%
 # mutate(did_wfh_labels = ifelse(is.na(did_wfh_labels),"Rural", did_wfh_labels))
mapdataboth 
mapdataboth <- svytable(~CanWorkFromHome+YEAR+countyFIP, design = dstrata)

mapdataboth <- mapdataboth %>% as_tibble() %>%
   group_by(YEAR, countyFIP) %>% 
     mutate(Prop = round(n/sum(n), digits =3)) %>%
   # filter(CanWorkFromHome == "Can WFH") %>%
filter(YEAR == 2021 & CanWorkFromHome == "Can WFH")%>%  

     full_join(countyIL, by = c("countyFIP" = "COUNTYFP"))

mapdataboth %>%
  filter(CanWorkFromHome == "Can WFH") %>%
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  labs(title = "Percent of county population that COULD work from home", subtitle = "Countyfips != 000", caption = "Note: Shows all counties with populations large enough to have their own values.
                                                           Rural counties went from ...
                                                           Counties had very small changes in occupations that COULD be done at work.") + 
  facet_wrap(~YEAR)+
  Alea_theme()+ 
   scale_fill_gradientn(colors = c("white", "darkblue"), na.value = "gray",
                        limits = c(0,.45),
      label = scales::percent)

Figure2a <- mapdataboth %>%
#filter(YEAR == 2021 & CanWorkFromHome == "Can WFH")%>%  
  ggplot(aes(fill = Prop)) +
  geom_sf(aes(geometry = geometry), color = "black")+ 
  # labs(title = "Work from Home Feasibility Rate", 
  #      subtitle = " Based on Occupation Characteristics", 
  #      caption = "Teleworkability based on D&N 2020 methodology. 
  #      OCCSOC codes from ACS 1 year Survey data at individual level.") +
 theme_void() + 
  theme(axis.ticks = element_blank(), axis.text = element_blank(),   
        plot.title = element_text(hjust = 0.5), plot.caption = element_text(hjust=.5),  
        plot.subtitle = element_text(hjust = 0.5)) +
   scale_fill_gradientn(colors = c("white", "darkblue"), na.value = "gray",
                       limits = c(0,.6),
                        name = "Labor Force with\nWFH Feasibility", 
                       label = scales::percent)

Figure2a

# ggsave("Figure2a.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
# ggsave("Figure2a.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure2a.png", limitsize = FALSE, width = 8, height = 4, units = "in")

Figure2b

# ggsave("Figure2b.eps", limitsize = FALSE,width = 8, height = 4, units = "in")
# ggsave("Figure2b.pdf", limitsize = FALSE,width = 8, height = 4, units = "in")
ggsave("Figure2b.png", limitsize = FALSE, width = 8, height = 4, units = "in")
mapdataboth <- joined %>% 
 # filter(CanWorkFromHome != "NA" )%>% # create percentages withing missing values included. aka valid percent.
   group_by(county_pop_type, YEAR, countyFIP) %>% 
   dplyr::summarize(weightedcount=sum(PERWT), #weighted 
                    unweightedcount = n(),
                    mean_telework = mean(teleworkable, na.rm=TRUE, weight = PERWT)
                    ) %>% 
   mutate(pct_weight = weightedcount/sum(weightedcount), 
          pct_noweight = unweightedcount/sum(unweightedcount)) %>%
  full_join(countyIL, by = c("countyFIP" = "COUNTYFP"))  %>%
    mutate(mean_telework = ifelse(is.na(county_pop_type), 0.2941470, mean_telework))
 #  mutate(pct_weight = ifelse(is.na(county_pop_type), 0.09237573, pct_weight))# %>%
 # mutate(did_wfh_labels = ifelse(is.na(did_wfh_labels),"Rural", did_wfh_labels))
mapdataboth
mapdataboth %>%
  filter(YEAR != "NA") %>%
  ggplot(aes(fill = mean_telework)) +
  geom_sf(aes(geometry = geometry), color = "black")+ labs(title = "Average teleworkable score for each County", subtitle = "Countyfips != 000", caption = "Note: Shows all counties with populations large enough to have their own values.
                                                           Uses teleworkable, a continuous variable, instead of CanWorkFromHome.
                                                           Counties had very small changes in occupations that COULD be done at work.") + 
  facet_wrap(~YEAR)+ 
  Alea_theme()+
  scale_fill_continuous(label = scales::percent, low = "white", high = "darkblue")

Mixed Geography

# 
pums_weighted <- joined %>%
  filter(YEAR == 2021) %>%
  mutate(county_pop_type = if_else(COUNTYFIP==0, "Rural Counties", "Urban Counties")
        ) %>%
  dplyr::group_by(PUMA, COUNTYFIP, county_pop_type) %>%
  dplyr::summarize(weighted_obs = sum(PERWT),
            mean_telework = mean(teleworkable, weight=PERWT, na.rm=TRUE),
         #   mean_canwfh = mean(CanWorkFromHome), ## not numeric variable
            mean_didwfh = mean(did_wfh, weight = PERWT, na.rm=TRUE),
            observs = n(),
            avg_inc = mean(INCEARN,na.rm=TRUE)
           # avg_inc_w = survey_mean(INCEARN, weight=PERWT
         ) %>%  #number of people the sample represents
  mutate(PUMA = str_pad(PUMA, 5, pad="0"),
         countyFIP = str_pad(COUNTYFIP, 3, pad = "0"))

pums_unweight <- joined %>% 
  filter(YEAR == 2021) %>%
    mutate(county_pop_type = if_else(COUNTYFIP==0, "Rural Counties", "Urban Counties")) %>%

  group_by(PUMA, COUNTYFIP, county_pop_type) %>% 
  summarize(unweight = n(),#unweighted number of observations
            mean_telework = mean(teleworkable,na.rm=TRUE ),
            mean_didwfh = mean(did_wfh, na.rm=TRUE),
            avg_inc = mean(INCEARN,na.rm=TRUE)) %>% 
  mutate(PUMA = str_pad(PUMA, 5, pad="0"),
         countyFIP = str_pad(COUNTYFIP, 3, pad = "0"))

plotweighted <- pumasIL %>% 
  left_join(pums_weighted, by = c("PUMACE10" = "PUMA"))

plotunweight <- pumasIL %>% 
  left_join(pums_unweight, by = c("PUMACE10" = "PUMA"))

## PUMA boundaries
plot(plotweighted["weighted_obs"])
plot(plotunweight["unweight"])


plot(plotweighted["avg_inc"])
#plot(plotweighted["avg_inc_w"])
plot(plotunweight["avg_inc"])
#plot(plotweighted["avg_inc_w"])

plot(plotweighted["mean_didwfh"])
plot(plotunweight["mean_didwfh"])



FIPweighted <- countyIL %>% left_join(pums_weighted, by = c("COUNTYFP" = "countyFIP"))
FIPunweight <- countyIL %>% left_join(pums_unweight, by = c("COUNTYFP" = "countyFIP"))
plot(FIPweighted["weighted_obs"])
plot(FIPunweight["unweight"])


plot(countyIL["COUNTYFP"])

Observations using CITY variable: identifies observations from Chicago.

88 distinct PUMA areas.

#joined %>% group_by(CITY) %>% distinct(CITY)
joined %>% group_by(PUMA) %>% summarize(observs = n())
joined %>% filter(INCEARN > 0) %>% group_by(PUMA) %>% summarize(observs = n())

joined %>% group_by(COUNTYFIP, PUMA) %>% summarize(observs = n())

joined %>% 
  group_by(COUNTYFIP, PUMA) %>% 
  summarize(observs = n(),
            avg_inc = mean(INCEARN),
            avg_inc_w= mean(INCEARN, weight = PERWT))

Geography Variable Notes

PUMAS vs COMMZONE vs COUNTIES

Link from Francis on COMZONE variable (Commuter Zones)

Interactive ESRI Map of all PUMA outlines

Article on calculating mean income for groups of geographies with ACS data

# State worked in:
#0=NA, 17=Illinois



# ipums_var_desc(data, PWSTATE2)

joined <- joined %>% 
  mutate(PWSTATE2_clean = as_factor(lbl_na_if(PWSTATE2, ~.val %in% c(0))))

joined %>% 
 dplyr::group_by(YEAR) %>%
  dplyr::summarize(workers=sum(PERWT)) %>% #number of people that match that observation
  dplyr::ungroup()%>%
 dplyr:: group_by(YEAR,PWSTATE2_clean)%>%
  mutate(pct = n()/workers)%>% 
  arrange(desc(pct))

Regression attempt

Regression for 2019 using survey object dstrata2019.

svyglm(did_wfh~race_cat+ SEX+ AGE +CIHISPEED*CINETHH + CanWorkFromHome+county_pop_type+NCHILD+MARST + NCHLT5, 
       design = dstrata2019) %>% summary()

Call:
svyglm(formula = did_wfh ~ race_cat + SEX + AGE + CIHISPEED * 
    CINETHH + CanWorkFromHome + county_pop_type + NCHILD + MARST + 
    NCHLT5, design = dstrata2019)

Survey design:
Called via srvyr

Coefficients: (2 not defined because of singularities)
                                Estimate Std. Error t value Pr(>|t|)    
(Intercept)                    0.0345217  0.0104269   3.311 0.000931 ***
race_catBlack                 -0.0122320  0.0062653  -1.952 0.050904 .  
race_catOther                 -0.0114607  0.0061772  -1.855 0.063558 .  
race_catWhite                  0.0095343  0.0053828   1.771 0.076525 .  
SEX                           -0.0002013  0.0024779  -0.081 0.935257    
AGE                            0.0010262  0.0001075   9.548  < 2e-16 ***
CIHISPEED                     -0.0015224  0.0003118  -4.883 1.05e-06 ***
CanWorkFromHomeNo WFH         -0.0397512  0.0030210 -13.158  < 2e-16 ***
CanWorkFromHomeSome WFH        0.0067206  0.0050862   1.321 0.186397    
county_pop_typeUrban Counties  0.0094306  0.0033490   2.816 0.004867 ** 
NCHILD                         0.0008573  0.0014664   0.585 0.558819    
MARST                         -0.0001586  0.0007825  -0.203 0.839395    
NCHLT5                         0.0087275  0.0035447   2.462 0.013817 *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for gaussian family taken to be 0.0486245)

Number of Fisher Scoring iterations: 2

Regression for 2021 using survey object dstrata2021.

svyglm(did_wfh~race_cat+ SEX+ CIHISPEED+CINETHH + occ_2dig_labels+CanWorkFromHome+county_pop_type, 
       design = dstrata2021) %>% summary()

Call:
svyglm(formula = did_wfh ~ race_cat + SEX + CIHISPEED + CINETHH + 
    occ_2dig_labels + CanWorkFromHome + county_pop_type, design = dstrata2021)

Survey design:
Called via srvyr

Coefficients: (1 not defined because of singularities)
                                                 Estimate Std. Error t value
(Intercept)                                     0.3393016  0.0153216  22.145
race_catBlack                                  -0.0518241  0.0123587  -4.193
race_catOther                                  -0.0695978  0.0111494  -6.242
race_catWhite                                  -0.0292016  0.0104570  -2.793
SEX                                            -0.0018776  0.0043479  -0.432
CIHISPEED                                      -0.0042004  0.0005485  -7.657
occ_2dig_labelsMilitary                        -0.0676503  0.0339870  -1.990
occ_2dig_labelsNatural Resources, Construction -0.0807753  0.0078252 -10.322
occ_2dig_labelsProduction, Transportation      -0.0887372  0.0066122 -13.420
occ_2dig_labelsSales & Office Jobs             -0.0462727  0.0065720  -7.041
occ_2dig_labelsService Occupations             -0.0849660  0.0066261 -12.823
CanWorkFromHomeNo WFH                          -0.1776687  0.0061142 -29.058
CanWorkFromHomeSome WFH                        -0.0006627  0.0082558  -0.080
county_pop_typeUrban Counties                   0.0925139  0.0050717  18.241
                                               Pr(>|t|)    
(Intercept)                                     < 2e-16 ***
race_catBlack                                  2.76e-05 ***
race_catOther                                  4.36e-10 ***
race_catWhite                                   0.00523 ** 
SEX                                             0.66587    
CIHISPEED                                      1.95e-14 ***
occ_2dig_labelsMilitary                         0.04655 *  
occ_2dig_labelsNatural Resources, Construction  < 2e-16 ***
occ_2dig_labelsProduction, Transportation       < 2e-16 ***
occ_2dig_labelsSales & Office Jobs             1.95e-12 ***
occ_2dig_labelsService Occupations              < 2e-16 ***
CanWorkFromHomeNo WFH                           < 2e-16 ***
CanWorkFromHomeSome WFH                         0.93602    
county_pop_typeUrban Counties                   < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for gaussian family taken to be 0.1387416)

Number of Fisher Scoring iterations: 2
svyglm(did_wfh~occ_2dig_labels*CanWorkFromHome+race_cat+ SEX+ age_cat +CIHISPEED*CINETHH + county_pop_type+NCHILD*NCHLT5+ MARST, 
       design = dstrata2021) %>% summary()

Call:
svyglm(formula = did_wfh ~ occ_2dig_labels * CanWorkFromHome + 
    race_cat + SEX + age_cat + CIHISPEED * CINETHH + county_pop_type + 
    NCHILD * NCHLT5 + MARST, design = dstrata2021)

Survey design:
Called via srvyr

Coefficients: (4 not defined because of singularities)
                                                                         Estimate
(Intercept)                                                             0.2997849
occ_2dig_labelsMilitary                                                -0.0201973
occ_2dig_labelsNatural Resources, Construction                         -0.0007279
occ_2dig_labelsProduction, Transportation                              -0.2506493
occ_2dig_labelsSales & Office Jobs                                     -0.0762230
occ_2dig_labelsService Occupations                                     -0.2066289
CanWorkFromHomeNo WFH                                                  -0.2231641
CanWorkFromHomeSome WFH                                                -0.0105891
race_catBlack                                                          -0.0458123
race_catOther                                                          -0.0636414
race_catWhite                                                          -0.0266417
SEX                                                                     0.0045197
age_cat25to34                                                           0.0537697
age_cat35to44                                                           0.0677273
age_cat45to54                                                           0.0469798
age_cat55to64                                                           0.0310501
age_cat65+                                                              0.0438510
CIHISPEED                                                              -0.0039661
county_pop_typeUrban Counties                                           0.0898251
NCHILD                                                                 -0.0116942
NCHLT5                                                                  0.0500957
MARST                                                                  -0.0023693
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeNo WFH   -0.0391172
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeNo WFH         0.2075487
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeNo WFH                0.0981888
occ_2dig_labelsService Occupations:CanWorkFromHomeNo WFH                0.1753075
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeSome WFH -0.2938396
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeSome WFH       0.3090120
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeSome WFH              0.0326471
occ_2dig_labelsService Occupations:CanWorkFromHomeSome WFH              0.1464021
NCHILD:NCHLT5                                                          -0.0111491
                                                                       Std. Error
(Intercept)                                                             0.0175238
occ_2dig_labelsMilitary                                                 0.0384065
occ_2dig_labelsNatural Resources, Construction                          0.2309994
occ_2dig_labelsProduction, Transportation                               0.0407972
occ_2dig_labelsSales & Office Jobs                                      0.0107413
occ_2dig_labelsService Occupations                                      0.0194278
CanWorkFromHomeNo WFH                                                   0.0077786
CanWorkFromHomeSome WFH                                                 0.0101903
race_catBlack                                                           0.0122784
race_catOther                                                           0.0109985
race_catWhite                                                           0.0101899
SEX                                                                     0.0043939
age_cat25to34                                                           0.0078624
age_cat35to44                                                           0.0084456
age_cat45to54                                                           0.0086643
age_cat55to64                                                           0.0085712
age_cat65+                                                              0.0107064
CIHISPEED                                                               0.0005539
county_pop_typeUrban Counties                                           0.0051601
NCHILD                                                                  0.0025797
NCHLT5                                                                  0.0130877
MARST                                                                   0.0012852
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeNo WFH    0.2311522
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeNo WFH         0.0413159
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeNo WFH                0.0141371
occ_2dig_labelsService Occupations:CanWorkFromHomeNo WFH                0.0206346
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeSome WFH  0.2318782
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeSome WFH       0.1621012
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeSome WFH              0.0186833
occ_2dig_labelsService Occupations:CanWorkFromHomeSome WFH              0.0558730
NCHILD:NCHLT5                                                           0.0046648
                                                                       t value
(Intercept)                                                             17.107
occ_2dig_labelsMilitary                                                 -0.526
occ_2dig_labelsNatural Resources, Construction                          -0.003
occ_2dig_labelsProduction, Transportation                               -6.144
occ_2dig_labelsSales & Office Jobs                                      -7.096
occ_2dig_labelsService Occupations                                     -10.636
CanWorkFromHomeNo WFH                                                  -28.689
CanWorkFromHomeSome WFH                                                 -1.039
race_catBlack                                                           -3.731
race_catOther                                                           -5.786
race_catWhite                                                           -2.615
SEX                                                                      1.029
age_cat25to34                                                            6.839
age_cat35to44                                                            8.019
age_cat45to54                                                            5.422
age_cat55to64                                                            3.623
age_cat65+                                                               4.096
CIHISPEED                                                               -7.160
county_pop_typeUrban Counties                                           17.408
NCHILD                                                                  -4.533
NCHLT5                                                                   3.828
MARST                                                                   -1.843
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeNo WFH    -0.169
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeNo WFH          5.023
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeNo WFH                 6.945
occ_2dig_labelsService Occupations:CanWorkFromHomeNo WFH                 8.496
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeSome WFH  -1.267
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeSome WFH        1.906
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeSome WFH               1.747
occ_2dig_labelsService Occupations:CanWorkFromHomeSome WFH               2.620
NCHILD:NCHLT5                                                           -2.390
                                                                       Pr(>|t|)
(Intercept)                                                             < 2e-16
occ_2dig_labelsMilitary                                                0.598974
occ_2dig_labelsNatural Resources, Construction                         0.997486
occ_2dig_labelsProduction, Transportation                              8.15e-10
occ_2dig_labelsSales & Office Jobs                                     1.31e-12
occ_2dig_labelsService Occupations                                      < 2e-16
CanWorkFromHomeNo WFH                                                   < 2e-16
CanWorkFromHomeSome WFH                                                0.298748
race_catBlack                                                          0.000191
race_catOther                                                          7.26e-09
race_catWhite                                                          0.008939
SEX                                                                    0.303668
age_cat25to34                                                          8.12e-12
age_cat35to44                                                          1.10e-15
age_cat45to54                                                          5.93e-08
age_cat55to64                                                          0.000292
age_cat65+                                                             4.22e-05
CIHISPEED                                                              8.21e-13
county_pop_typeUrban Counties                                           < 2e-16
NCHILD                                                                 5.83e-06
NCHLT5                                                                 0.000130
MARST                                                                  0.065266
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeNo WFH   0.865619
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeNo WFH        5.10e-07
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeNo WFH               3.84e-12
occ_2dig_labelsService Occupations:CanWorkFromHomeNo WFH                < 2e-16
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeSome WFH 0.205087
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeSome WFH      0.056621
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeSome WFH             0.080577
occ_2dig_labelsService Occupations:CanWorkFromHomeSome WFH             0.008790
NCHILD:NCHLT5                                                          0.016852
                                                                          
(Intercept)                                                            ***
occ_2dig_labelsMilitary                                                   
occ_2dig_labelsNatural Resources, Construction                            
occ_2dig_labelsProduction, Transportation                              ***
occ_2dig_labelsSales & Office Jobs                                     ***
occ_2dig_labelsService Occupations                                     ***
CanWorkFromHomeNo WFH                                                  ***
CanWorkFromHomeSome WFH                                                   
race_catBlack                                                          ***
race_catOther                                                          ***
race_catWhite                                                          ** 
SEX                                                                       
age_cat25to34                                                          ***
age_cat35to44                                                          ***
age_cat45to54                                                          ***
age_cat55to64                                                          ***
age_cat65+                                                             ***
CIHISPEED                                                              ***
county_pop_typeUrban Counties                                          ***
NCHILD                                                                 ***
NCHLT5                                                                 ***
MARST                                                                  .  
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeNo WFH      
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeNo WFH        ***
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeNo WFH               ***
occ_2dig_labelsService Occupations:CanWorkFromHomeNo WFH               ***
occ_2dig_labelsNatural Resources, Construction:CanWorkFromHomeSome WFH    
occ_2dig_labelsProduction, Transportation:CanWorkFromHomeSome WFH      .  
occ_2dig_labelsSales & Office Jobs:CanWorkFromHomeSome WFH             .  
occ_2dig_labelsService Occupations:CanWorkFromHomeSome WFH             ** 
NCHILD:NCHLT5                                                          *  
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for gaussian family taken to be 0.1374397)

Number of Fisher Scoring iterations: 2
svyglm(did_wfh~NCHLT5+factor(SEX) +factor(MARST)+factor(CINETHH) + occ_2dig_labels+county_pop_type, 
       design = dstrata2021,   ) %>% summary()

Call:
svyglm(formula = did_wfh ~ NCHLT5 + factor(SEX) + factor(MARST) + 
    factor(CINETHH) + occ_2dig_labels + county_pop_type, design = dstrata2021)

Survey design:
Called via srvyr

Coefficients:
                                                Estimate Std. Error t value
(Intercept)                                     0.221294   0.005888  37.587
NCHLT5                                          0.018093   0.005725   3.160
factor(SEX)2                                   -0.001916   0.004300  -0.445
factor(MARST)2                                 -0.014876   0.017142  -0.868
factor(MARST)3                                 -0.046180   0.015757  -2.931
factor(MARST)4                                 -0.018821   0.007405  -2.542
factor(MARST)5                                 -0.048819   0.015496  -3.151
factor(MARST)6                                 -0.018574   0.004970  -3.737
factor(CINETHH)2                               -0.011168   0.015357  -0.727
factor(CINETHH)3                               -0.045969   0.010388  -4.425
occ_2dig_labelsMilitary                        -0.227347   0.033069  -6.875
occ_2dig_labelsNatural Resources, Construction -0.228779   0.006730 -33.992
occ_2dig_labelsProduction, Transportation      -0.234196   0.005352 -43.755
occ_2dig_labelsSales & Office Jobs             -0.086346   0.006446 -13.396
occ_2dig_labelsService Occupations             -0.214796   0.005603 -38.336
county_pop_typeUrban Counties                   0.097819   0.004613  21.204
                                               Pr(>|t|)    
(Intercept)                                     < 2e-16 ***
NCHLT5                                         0.001578 ** 
factor(SEX)2                                   0.655995    
factor(MARST)2                                 0.385502    
factor(MARST)3                                 0.003385 ** 
factor(MARST)4                                 0.011041 *  
factor(MARST)5                                 0.001631 ** 
factor(MARST)6                                 0.000186 ***
factor(CINETHH)2                               0.467079    
factor(CINETHH)3                               9.66e-06 ***
occ_2dig_labelsMilitary                        6.31e-12 ***
occ_2dig_labelsNatural Resources, Construction  < 2e-16 ***
occ_2dig_labelsProduction, Transportation       < 2e-16 ***
occ_2dig_labelsSales & Office Jobs              < 2e-16 ***
occ_2dig_labelsService Occupations              < 2e-16 ***
county_pop_typeUrban Counties                   < 2e-16 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for gaussian family taken to be 0.1417135)

Number of Fisher Scoring iterations: 2

Very simple interpretation: Compared to Business and Finance occupations who Can Work From Home in Rural Counties without any children under 5

Increases likelihood of working from home: Number of Children under 5 increases odds of working from home, living in an “Urban” County (higher pop. density),

Decreases liklihood of woring from home: Lacking access to internet, WFH not feasible & occupation labels within Production and Transportation,

Other Sources and Papers

Ability to work from home: evidence from two surveys and implications for the labor market in the COVID-19 pandemic. June 2020. BLS Monthly Labor Review

  • Authors used Current Population Survey data and O*NET job-content data to categorize jobs as able or unable to telework. Followed Dingel & Neiman’s methodology of classifying telework feasibility and merging with data from American Time Use Survey (ATUS)

  • Compares ability to work from home with actual occurance of working from home based on American Time Use Survey and Occupational Information Network (O*NET). Also uses Current Population Survey data to look at how effects differed between occupations where telework was feasible or not.