Init

library(kirkegaard)
## Loading required package: tidyverse
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.1
## ✔ ggplot2   3.5.2     ✔ tibble    3.2.1
## ✔ lubridate 1.9.4     ✔ tidyr     1.3.1
## ✔ purrr     1.0.4     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
## Loading required package: magrittr
## 
## 
## Attaching package: 'magrittr'
## 
## 
## The following object is masked from 'package:purrr':
## 
##     set_names
## 
## 
## The following object is masked from 'package:tidyr':
## 
##     extract
## 
## 
## Loading required package: weights
## 
## Loading required package: Hmisc
## 
## 
## Attaching package: 'Hmisc'
## 
## 
## The following objects are masked from 'package:dplyr':
## 
##     src, summarize
## 
## 
## The following objects are masked from 'package:base':
## 
##     format.pval, units
## 
## 
## Loading required package: assertthat
## 
## 
## Attaching package: 'assertthat'
## 
## 
## The following object is masked from 'package:tibble':
## 
##     has_name
## 
## 
## Loading required package: psych
## 
## 
## Attaching package: 'psych'
## 
## 
## The following object is masked from 'package:Hmisc':
## 
##     describe
## 
## 
## The following objects are masked from 'package:ggplot2':
## 
##     %+%, alpha
## 
## 
## 
## Attaching package: 'kirkegaard'
## 
## 
## The following object is masked from 'package:psych':
## 
##     rescale
## 
## 
## The following object is masked from 'package:assertthat':
## 
##     are_equal
## 
## 
## The following object is masked from 'package:purrr':
## 
##     is_logical
## 
## 
## The following object is masked from 'package:base':
## 
##     +
load_packages(
  readxl,
  patchwork,
  GGally
)
## Registered S3 method overwritten by 'GGally':
##   method from   
##   +.gg   ggplot2
theme_set(theme_bw())

options(
    digits = 3
)

#multithreading
#library(future)
#plan(multisession(workers = 8))

Functions

Data

#paid leave data
paid_leave1 = read_csv("data/Length of paid leave (calendar days)  [WB Gender Portal]/Length of paid leave (calendar days) .csv") %>% df_legalize_names()
## Rows: 217 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Economy, Economy Code
## dbl (2): Year, Length of paid maternity leave (calendar days)
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
paid_leave2 = read_csv("data/Length of paid leave (calendar days)  [WB Gender Portal] (1)/Length of paid leave (calendar days) .csv") %>% df_legalize_names()
## Rows: 217 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Economy, Economy Code
## dbl (2): Year, Length of paid paternity leave (calendar days)
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
paid_leave3 = read_csv("data/Length of paid leave (calendar days)  [WB Gender Portal] (2)/Length of paid leave (calendar days) .csv") %>% df_legalize_names()
## Rows: 217 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Economy, Economy Code
## dbl (2): Year, Length of paid shared parental leave (calendar days)
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#fert
fert = read_excel("data/WPP2024_GEN_F01_DEMOGRAPHIC_INDICATORS_COMPACT.xlsx", skip = 16, guess_max = 10000) %>% 
  filter(!is.na(`ISO3 Alpha-code`)) %>% 
  df_legalize_names() %>%
  select(ISO3_Alpha_code, Year, Total_Fertility_Rate_live_births_per_woman) %>% 
  rename(
    ISO = ISO3_Alpha_code,
    TFR = Total_Fertility_Rate_live_births_per_woman
  ) %>% mutate(
    TFR = as.numeric(TFR)
  )

#median income
median_inc = read_csv("data/median-income-by-country-2023.csv")
## Rows: 162 Columns: 5
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (1): country
## dbl (4): medianIncome, meanIncome, gdpPerCapitaPPP, pop2023
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#replace 0's with NA
median_inc$gdpPerCapitaPPP %<>% mapvalues(0, NA)
median_inc$meanIncome %<>% mapvalues(0, NA)
## The following `from` values were not present in `x`: 0
median_inc$medianIncome %<>% mapvalues(0, NA)

#gdp per capita
gdp = read_csv("data/gdp-per-capita-worldbank/gdp-per-capita-worldbank.csv") %>% df_legalize_names() %>% filter(Year == 2019)
## Rows: 7063 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Entity, Code
## dbl (2): Year, GDP per capita, PPP (constant 2021 international $)
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
#join
d = full_join(
  paid_leave1 %>% rename(ISO = Economy_Code, maternal_leave = Length_of_paid_maternity_leave_calendar_days) %>% select(ISO, maternal_leave),
  paid_leave2 %>% rename(ISO = Economy_Code, paternal_leave = Length_of_paid_paternity_leave_calendar_days) %>% select(ISO, paternal_leave)
) %>% full_join(
  paid_leave3 %>% rename(ISO = Economy_Code, shared_leave = Length_of_paid_shared_parental_leave_calendar_days) %>% select(ISO, shared_leave)
) %>% full_join(
  fert %>% filter(Year == 2023) %>% select(ISO, TFR)
) %>% full_join(
  median_inc %>% mutate(ISO = pu_translate(country)) %>% select(-country)
) %>% full_join(
  gdp %>% rename(ISO = Code, GDPpc = GDP_per_capita_PPP_constant_2021_international) %>% select(ISO, GDPpc) %>% filter(!is.na(ISO))
)
## Joining with `by = join_by(ISO)`
## Joining with `by = join_by(ISO)`
## Joining with `by = join_by(ISO)`
## Joining with `by = join_by(ISO)`
## Joining with `by = join_by(ISO)`
#data check
assert_that(!anyDuplicated(d$ISO))
## [1] TRUE

Analysis

#correlations
d %>% 
  select(TFR, maternal_leave, paternal_leave, shared_leave) %>% 
  ggpairs()
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).

GG_save("figs/ggpairs.png")
## Warning: Removed 3 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).
## Warning in ggally_statistic(data = data, mapping = mapping, na.rm = na.rm, :
## Removed 51 rows containing missing values
## Warning: Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Removed 51 rows containing missing values or values outside the scale range
## (`geom_point()`).
## Warning: Removed 51 rows containing non-finite outside the scale range
## (`stat_density()`).
#regression models
d_std = d %>% df_standardize()
## Skipped ISO because it is a character (string)
list(
  lm(TFR ~ maternal_leave + paternal_leave, data = d_std),
  lm(TFR ~ maternal_leave + paternal_leave + medianIncome, data = d_std),
  lm(TFR ~ maternal_leave + paternal_leave + GDPpc, data = d_std)
) %>% 
  summarize_models(asterisks_only = F) %>% flextable::flextable()

Predictor/Model

1

2

3

(Intercept)

0.10 (0.075, 0.181)

0.17 (0.066, 0.011)

0.04 (0.062, 0.503)

maternal_leave

-0.13 (0.077, 0.099)

-0.21 (0.068, 0.002**)

-0.16 (0.065, 0.018)

paternal_leave

-0.18 (0.077, 0.02)

-0.02 (0.066, 0.767)

-0.02 (0.065, 0.702)

medianIncome

-0.63 (0.069, <0.001***)

GDPpc

-0.66 (0.068, <0.001***)

R2 adj.

0.045

0.385

0.369

N

189

157

184

Meta

#versions
write_sessioninfo()
## R version 4.5.0 (2025-04-11)
## Platform: x86_64-pc-linux-gnu
## Running under: Linux Mint 21.1
## 
## Matrix products: default
## BLAS:   /usr/lib/x86_64-linux-gnu/blas/libblas.so.3.10.0 
## LAPACK: /usr/lib/x86_64-linux-gnu/lapack/liblapack.so.3.10.0  LAPACK version 3.10.0
## 
## locale:
##  [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
##  [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
##  [5] LC_MONETARY=en_DK.UTF-8    LC_MESSAGES=en_US.UTF-8   
##  [7] LC_PAPER=en_DK.UTF-8       LC_NAME=C                 
##  [9] LC_ADDRESS=C               LC_TELEPHONE=C            
## [11] LC_MEASUREMENT=en_DK.UTF-8 LC_IDENTIFICATION=C       
## 
## time zone: Europe/Brussels
## tzcode source: system (glibc)
## 
## attached base packages:
## [1] stats     graphics  grDevices utils     datasets  methods   base     
## 
## other attached packages:
##  [1] GGally_2.2.1          patchwork_1.3.0       readxl_1.4.5         
##  [4] kirkegaard_2025-03-12 psych_2.5.3           assertthat_0.2.1     
##  [7] weights_1.0.4         Hmisc_5.2-3           magrittr_2.0.3       
## [10] lubridate_1.9.4       forcats_1.0.0         stringr_1.5.1        
## [13] dplyr_1.1.4           purrr_1.0.4           readr_2.1.5          
## [16] tidyr_1.3.1           tibble_3.2.1          ggplot2_3.5.2        
## [19] tidyverse_2.0.0      
## 
## loaded via a namespace (and not attached):
##   [1] Rdpack_2.6.4            mnormt_2.1.1            gridExtra_2.3          
##   [4] rlang_1.1.6             compiler_4.5.0          gdata_3.0.1            
##   [7] systemfonts_1.2.2       vctrs_0.6.5             pkgconfig_2.0.3        
##  [10] shape_1.4.6.1           crayon_1.5.3            fastmap_1.2.0          
##  [13] backports_1.5.0         labeling_0.4.3          rmarkdown_2.29         
##  [16] tzdb_0.5.0              nloptr_2.2.1            ragg_1.4.0             
##  [19] bit_4.6.0               xfun_0.52               glmnet_4.1-8           
##  [22] jomo_2.7-6              cachem_1.1.0            jsonlite_2.0.0         
##  [25] uuid_1.2-1              pan_1.9                 broom_1.0.8            
##  [28] parallel_4.5.0          cluster_2.1.8.1         R6_2.6.1               
##  [31] bslib_0.9.0             stringi_1.8.7           RColorBrewer_1.1-3     
##  [34] boot_1.3-31             rpart_4.1.24            jquerylib_0.1.4        
##  [37] cellranger_1.1.0        Rcpp_1.0.14             iterators_1.0.14       
##  [40] knitr_1.50              base64enc_0.1-3         Matrix_1.7-3           
##  [43] splines_4.5.0           nnet_7.3-20             timechange_0.3.0       
##  [46] tidyselect_1.2.1        rstudioapi_0.17.1       yaml_2.3.10            
##  [49] codetools_0.2-19        lattice_0.22-5          plyr_1.8.9             
##  [52] withr_3.0.2             askpass_1.2.1           flextable_0.9.7        
##  [55] evaluate_1.0.3          foreign_0.8-90          survival_3.8-3         
##  [58] ggstats_0.9.0           zip_2.3.2               xml2_1.3.8             
##  [61] pillar_1.10.2           mice_3.17.0             checkmate_2.3.2        
##  [64] foreach_1.5.2           reformulas_0.4.0        generics_0.1.3         
##  [67] vroom_1.6.5             hms_1.1.3               munsell_0.5.1          
##  [70] scales_1.3.0            minqa_1.2.8             gtools_3.9.5           
##  [73] glue_1.8.0              gdtools_0.4.2           tools_4.5.0            
##  [76] data.table_1.17.0       lme4_1.1-37             grid_4.5.0             
##  [79] rbibutils_2.3           colorspace_2.1-1        nlme_3.1-168           
##  [82] htmlTable_2.4.3         Formula_1.2-5           cli_3.6.4              
##  [85] textshaping_1.0.0       officer_0.6.8           fontBitstreamVera_0.1.1
##  [88] gtable_0.3.6            fontquiver_0.2.1        sass_0.4.10            
##  [91] digest_0.6.37           htmlwidgets_1.6.4       farver_2.1.2           
##  [94] htmltools_0.5.8.1       lifecycle_1.0.4         mitml_0.4-5            
##  [97] openssl_2.3.2           fontLiberation_0.1.0    bit64_4.6.0-1          
## [100] MASS_7.3-65
#write data to file for reuse
d %>% write_rds("data/data_for_reuse.rds")

#OSF
if (F) {
  library(osfr)
  
  #login
  osf_auth(readr::read_lines("~/.config/osf_token"))
  
  #the project we will use
  osf_proj = osf_retrieve_node("https://osf.io/XXX/")
  
  #upload all files in project
  #overwrite existing (versioning)
  osf_upload(
    osf_proj,
    path = c("data", "figures", "papers", "notebook.Rmd", "notebook.html", "sessions_info.txt"), 
    conflicts = "overwrite"
    )
}