We constructed the following database for this analysis (df):
| Variable | Description |
|---|---|
| id | Identification code |
| dob | Date of birth (mm/dd/yyyy) |
| ma0fe1 | Sex, male = 0 and female = 1 |
| cogdevdate | Date of neurodevelopment visit (mm/dd/yyyy) |
| cogdevage | Age at cognitive development testing, in months |
| cognitive | BSD-III cognitive composite score |
| language | BSD-III language composite score |
| motor | BSD-III motor composite score |
| cognitive_perc | Percentile of BSD-III cognitive composite score |
| language_perc | Percentile of BSD-III language composite score |
| motor_perc | Percentile of BSD-III motor composite score |
| anthrodate | Date of anthropometric measurement (mm/dd/yyyy) |
| anthroage | Age at anthropometric measurement, in months |
| height | Height in cm, 1 decimal point |
| weight | Weight in kg, 1 decimal point |
| haz | Height for age z-score, WHO MGRS standard |
| whz | Weight for height z-score, WHO MGRS standard |
| waz | Weight for age z-score, WHO MGRS standard |
| gabirth | Gestational age at birth, in days |
| BMI | Weight in kg / height^2 in m |
| BAZ | Body mass index for age, WHO reference |
| hbdate | Date of hemoglobin assessment (mm/dd/yyyy) |
| hbage | Age at hemoglobin assessment, in months |
| hb | Hemoglobin concentration, g/dl |
| spo2date | Date of pulse oximetry measurement (mm/dd/yyyy) |
| spo2age | Age at pulse oximetry measurement, in months |
| spo2 | Oxyhemoglobin saturation (%) as average of SpO2 at 60, 90 and 120 s |
| lpg | Intervention = 1, control = 0 |
| province | 1 = Puno, 2 = San Roman, 3 = Azangaro/Lampa, 4 = Chicuito, 5 = Huancane/Moho, 6 = El Collao |
| baselinedate | Baseline visit date (mm/dd/yyyy) |
| blpm | Maternal personal exposure to PM2.5 in µg/m3 |
| blbc | Maternal personal exposure to black carbon in µg/m3 |
| blco | Maternal personal exposure to carbon monoxide in ppm |
| p1date | P1 visit date |
| p1pm | Maternal personal exposure to PM2.5 in µg/m3 |
| p2bc | Maternal personal exposure to black carbon in µg/m3 |
| p2co | Maternal personal exposure to carbon monoxide in ppm |
| birthlength | Length at birth in cm, 1 decimal point |
| birthlaz | Length for age z-score at birth, WHO MGRS standard |
| birthlaz_21 | Length for age z-score at birth, INTERGROWTH 21st |
| birthweight | Weight at birth in g |
| birthwaz | Weight for age at birth, WHO MGRS standard |
| birthwaz_21 | Weight for age at birth, INTERGROWTH 21st |
| b1date | Date of B1 visit (mm/dd/yyyy) |
| b1length | Length at B1 visit (~3 months) in cm, 1 decimal point |
| b1laz | Length for age z-score for B1 visit, WHO MGRS standard |
| b1laz_21 | Length for age z-score for B1 visit, INTERGROWTH 21st |
| b2date | Date of B2 visit (mm/dd/yyyy) |
| b2length | Length at B2 visit (~5 months) in cm, 1 decimal point |
| b2laz | Length for age z-score for B2 visit, WHO MGRS standard |
| b2laz_21 | Length for age z-score for B2 visit, INTERGROWTH 21st |
| b3date | Date of B3 visit (mm/dd/yyyy) |
| b3length | Length at B1 visit (~9 months) in cm, 1 decimal point |
| b3laz | Length for age z-score for B3 visit, WHO MGRS standard |
| b3laz_21 | Length for age z-score for B3 visit, INTERGROWTH 21st |
| b4date | Date of B4 visit (mm/dd/yyyy) |
| b4length | Length at B4 visit (~12 months) in cm, 1 decimal point |
| b4laz | Length for age z-score for B4 visit, WHO MGRS standard |
| b4laz_21 | Length for age z-score for B4 visit, INTERGROWTH 21st |
| b1pm | Indirect child PM2.5 concentration in µg/m3 |
| b2pm | Indirect child PM2.5 concentration in µg/m3 |
| b4pm | Indirect child PM2.5 concentration in µg/m3 |
| b1co | Indirect child CO concentration in ppm |
| b2co | Indirect child CO concentration in ppm |
| b4co | Indirect child CO concentration in ppm |
| sesindex | Socioeconomic index |
| momeduc | Maternal education, in years |
| birthorder | Child’s order of birth |
| momage | Maternal age in years |
| momheight | Maternal height in cm |
| momweight | Maternal weight in kg |
| bankaccount | yes=1, no=0 |
| tv | yes=1, no=0 |
| radio | yes=1, no=0 |
| phone | yes=1, no=0 |
| preterm | yes=1, no=0 |
| nulliparity | yes=1, no=0 |
| living | Number of people living in the house |
| mdds | Maternal diversity dietary score |
| foodinsecurity | Food insecurity score |
| anyonesmoke | Any smoking in household, yes=1, no=0 |
We constructed the following variables using the code below:
| Variable | Description |
|---|---|
| pm | Mean of PM2.5 between baseline and B4. |
| prenatalpm | Mean of PM2.5 between baseline and P2. |
| prenatalpm_postrand | Mean of PM2.5 between P1 and P2. |
| postnatalpm | Mean of PM2.5 between B1 and B4. |
| co | Mean of carbon monoxide between baseline and B4. |
| prenatalco | Mean of carbon monoxide between baseline and P2. |
| postnatalco | Mean of carbon monoxide between B1 and B4. |
| prenatalco_postrand | Mean of carbon monoxide between P1 and P2. |
| iqrdiffpm | 25th and 75th percentiles of average PM2.5. |
| iqrdiffco | 25th and 75th percentiles of carbon monoxide. |
| iqrdiffpm_prenatal | 25th and 75th percentiles of average prenatal PM2.5. |
| iqrdiffpm_postnatal | 25th and 75th percentiles of average post-natal PM2.5. |
| iqrdifffco_prenatal | 25th and 75th percentiles of average prenatal carbon monoxide. |
| iqrdiffco_postnatal | 25th and 75th percentiles of average post-natal carbon monoxide. |
# library(dplyr)
# Calculate means and round to two decimal places
df_c1 <- df %>%
rowwise() %>%
mutate(pm = round(mean(c_across(c(blpm, p1pm, p2pm, b1pm, b2pm, b4pm)), na.rm = TRUE),
2), prenatalpm = round(mean(c_across(c(blpm, p1pm, p2pm)), na.rm = TRUE),
2), postnatalpm = round(mean(c_across(c(b1pm, b2pm, b4pm)), na.rm = TRUE),
2), co = round(mean(c_across(c(blco, p1co, p2co, b1co, b2co, b4co)), na.rm = TRUE),
2), prenatalco = round(mean(c_across(c(blco, p1co, p2co)), na.rm = TRUE),
2), postnatalco = round(mean(c_across(c(b1co, b2co, b4co)), na.rm = TRUE),
2), prenatalpm_postrand = round(mean(c_across(c(p1pm, p2pm)), na.rm = TRUE),
2), prenatalco_postrand = round(mean(c_across(c(p1co, p2co)), na.rm = TRUE),
2))
# Replace NaN values with NA for each column separately
for (col in colnames(df_c1)) {
df_c1[[col]][is.nan(df_c1[[col]])] <- NA
}
# cat('Dataset with ', dim(df_c1)[1], 'rows and', dim(df_c1)[2], 'columns\n')
# paged_table(df_c1, options = list(rows.print = 10, cols.print = 5))
# Calculate means and round to two decimal places
df2_c1 <- df2 %>%
rowwise() %>%
mutate(pm = round(mean(c_across(c(blpm, p1pm, p2pm, b1pm, b2pm, b4pm)), na.rm = TRUE),
2), prenatalpm = round(mean(c_across(c(blpm, p1pm, p2pm)), na.rm = TRUE),
2), postnatalpm = round(mean(c_across(c(b1pm, b2pm, b4pm)), na.rm = TRUE),
2), co = round(mean(c_across(c(blco, p1co, p2co, b1co, b2co, b4co)), na.rm = TRUE),
2), prenatalco = round(mean(c_across(c(blco, p1co, p2co)), na.rm = TRUE),
2), postnatalco = round(mean(c_across(c(b1co, b2co, b4co)), na.rm = TRUE),
2), prenatalpm_postrand = round(mean(c_across(c(p1pm, p2pm)), na.rm = TRUE),
2), prenatalco_postrand = round(mean(c_across(c(p1co, p2co)), na.rm = TRUE),
2))
# Replace NaN values with NA for each column separately
for (col in colnames(df2_c1)) {
df2_c1[[col]][is.nan(df2_c1[[col]])] <- NA
}
# cat('Dataset with ', dim(df2_c1)[1], 'rows and', dim(df2_c1)[2], 'columns\n')
# paged_table(df2_c1, options = list(rows.print = 10, cols.print = 5))df_c2 <- df_c1 %>%
dplyr::mutate(foodsecure = ifelse(foodinsecurity == 3, 1, 0), mild = ifelse(foodinsecurity ==
2, 1, 0), moderateorsevere = ifelse(foodinsecurity == 1, 1, 0), low = ifelse(mdds ==
0, 1, 0), medium = ifelse(mdds == 1, 1, 0), high = ifelse(mdds == 2, 1, 0))
var_label_list <- list(momage = "Maternal age in years", momheight = "Maternal height in cm",
bankaccount = "Bank account, n", tv = "Television, n", radio = "Radio, n", phone = "Cellular telephone, n",
momeduc = "Maternal education, number of years", living = "Number of people living in the house",
sesindex = "Socioeconomic wealth index", gabirth = "Gestational age, days", nulliparity = "Nulliparous, n",
preterm = "Pre-term birth, n", low = "Low (Less than 4), n", medium = "Medium (4-5), n",
high = "High (More than 5), n", foodsecure = "Food secure, n", mild = "Mild (1–3), n",
moderateorsevere = "Moderate or severe (4 – 8), n", anyonesmoke = "Smoking in the household, n",
blpm = "Baseline", prenatalpm_postrand = "Prenatal, post-randomization (P1 and P2 visits)",
postnatalpm = "Post-natal, post-randomization (B1, B2 and B4 visits)", blco = "Baseline",
prenatalco_postrand = "Prenatal, post-randomization (P1 and P2 visits)", postnatalco = "Post-natal, post-randomization (B1, B2 and B4 visits)")
labelled::var_label(df_c2) <- var_label_list
fvars <- c("bankaccount", "tv", "radio", "phone", "nulliparity", "preterm", "low",
"medium", "high", "foodsecure", "mild", "moderateorsevere", "anyonesmoke")
df_c2[fvars] <- lapply(df_c2[fvars], factor)
vars <- names(var_label_list)
table1 <- CreateTableOne(vars = vars, strata = "lpg", data = df_c2, factorVars = fvars,
testApprox = chisq.test, argsApprox = list(correct = TRUE), testExact = fisher.test,
argsExact = list(workspace = 2 * 10^5), testNormal = oneway.test, argsNormal = list(var.equal = TRUE),
testNonNormal = kruskal.test, argsNonNormal = list(NULL))
kable1 <- print(table1, nonnormal = c(), showAllLevels = F, formatOptions = list(big.mark = ","),
explain = T, varLabels = TRUE, printToggle = T, catDigits = 1, contDigits = 1)| Variable | Control | Intervention | P-value |
|---|---|---|---|
| n | 136 | 165 | |
| Demographics | |||
| Maternal age in years (mean (SD)) | 25.5 (4.8) | 25.8 (4.3) | 0.566 |
| Maternal height in cm (mean (SD)) | 152.5 (4.2) | 152.8 (4.5) | 0.492 |
| Socioeconomic status indicators | |||
| Bank account, n (%) | 38 (27.9) | 51 (30.9) | 0.664 |
| Television, n (%) | 94 (69.1) | 113 (68.5) | 1.000 |
| Radio, n (%) | 103 (75.7) | 121 (73.3) | 0.732 |
| Cellular telephone, n (%) | 128 (94.1) | 157 (95.2) | 0.889 |
| Maternal education, number of years (mean (SD)) | 4.6 (1.0) | 4.5 (1.1) | 0.293 |
| Number of people living in the house (mean (SD)) | 4.7 (1.9) | 4.5 (1.7) | 0.284 |
| Socioeconomic wealth index (mean (SD)) | 0.5 (0.5) | 0.5 (0.6) | 0.329 |
| Pregnancy factors | |||
| Gestational age, days (mean (SD)) | 274.9 (10.0) | 275.2 (10.2) | 0.797 |
| Nulliparous, n (%) | 51 (37.5) | 65 (39.6) | 0.796 |
| Pre-term birth, n (%) | 7 ( 5.1) | 12 ( 7.3) | 0.605 |
| Minimum dietary diversity | |||
| Low (Less than 4), n (%) | 14 (10.3) | 20 (12.1) | 0.752 |
| Medium (4-5), n (%) | 88 (64.7) | 94 (57.0) | 0.212 |
| High (More than 5), n (%) | 34 (25.0) | 51 (30.9) | 0.315 |
| Household food insecurity | |||
| Food secure, n (%) | 65 (49.6) | 74 (46.0) | 0.614 |
| Mild (1–3), n (%) | 49 (37.4) | 61 (37.9) | 1.000 |
| Moderate or severe (4 – 8), n (%) | 17 (13.0) | 26 (16.1) | 0.552 |
| Smoking in the household, n (%) | |||
| Smoking in the household, n (%) | 2 ( 1.5) | 1 ( 0.6) | 0.866 |
| Average personal exposure to fine particulate matter in µg/m3, mean (SD) | |||
| Baseline (mean (SD)) | 72.6 (76.5) | 81.7 (83.5) | 0.366 |
| Prenatal, post-randomization (P1 and P2 visits) (mean (SD)) | 63.0 (79.2) | 23.2 (36.7) | <0.001 |
| Post-natal, post-randomization (B1, B2 and B4 visits) (mean (SD)) | 62.8 (136.2) | 26.3 (69.7) | 0.005 |
| Average personal exposure to carbon monoxide in ppm, mean (SD) | |||
| Baseline (mean (SD)) | 3.2 (5.5) | 3.9 (5.8) | 0.321 |
| Prenatal, post-randomization (P1 and P2 visits) (mean (SD)) | 2.9 (5.1) | 1.3 (1.7) | <0.001 |
| Post-natal, post-randomization (B1, B2 and B4 visits) (mean (SD)) | 3.1 (4.2) | 2.1 (3.9) | 0.041 |
df2_c2 <- df2_c1 %>%
dplyr::mutate(foodsecure = ifelse(foodinsecurity == 3, 1, 0), mild = ifelse(foodinsecurity ==
2, 1, 0), moderateorsevere = ifelse(foodinsecurity == 1, 1, 0), low = ifelse(mdds ==
0, 1, 0), medium = ifelse(mdds == 1, 1, 0), high = ifelse(mdds == 2, 1, 0))
var_label_list <- list(momage = "Maternal age in years", momheight = "Maternal height in cm",
bankaccount = "Bank account, n", tv = "Television, n", radio = "Radio, n", phone = "Cellular telephone, n",
momeduc = "Maternal education, number of years", living = "Number of people living in the house",
sesindex = "Socioeconomic wealth index", gabirth = "Gestational age, days", nulliparity = "Nulliparous, n",
preterm = "Pre-term birth, n", low = "Low (Less than 4), n", medium = "Medium (4-5), n",
high = "High (More than 5), n", foodsecure = "Food secure, n", mild = "Mild (1–3), n",
moderateorsevere = "Moderate or severe (4 – 8), n", anyonesmoke = "Smoking in the household, n",
blpm = "Baseline", prenatalpm_postrand = "Prenatal, post-randomization (P1 and P2 visits)",
postnatalpm = "Post-natal, post-randomization (B1, B2 and B4 visits)", blco = "Baseline",
prenatalco_postrand = "Prenatal, post-randomization (P1 and P2 visits)", postnatalco = "Post-natal, post-randomization (B1, B2 and B4 visits)")
labelled::var_label(df2_c2) <- var_label_list
fvars <- c("bankaccount", "tv", "radio", "phone", "nulliparity", "preterm", "low",
"medium", "high", "foodsecure", "mild", "moderateorsevere", "anyonesmoke")
df2_c2[fvars] <- lapply(df2_c2[fvars], factor)
vars <- names(var_label_list)
table2 <- CreateTableOne(vars = vars, strata = "subset", data = df2_c2, factorVars = fvars,
testApprox = chisq.test, argsApprox = list(correct = TRUE), testExact = fisher.test,
argsExact = list(workspace = 2 * 10^5), testNormal = oneway.test, argsNormal = list(var.equal = TRUE),
testNonNormal = kruskal.test, argsNonNormal = list(NULL))
kable2 <- print(table2, nonnormal = c(), showAllLevels = F, formatOptions = list(big.mark = ","),
explain = T, varLabels = TRUE, printToggle = T, catDigits = 1, contDigits = 1)| Variable | Not visited during follow-up | Follow-up sample | P-value |
|---|---|---|---|
| n | 442 | 301 | |
| Demographics | |||
| Maternal age in years (mean (SD)) | 25.4 (4.5) | 25.6 (4.5) | 0.493 |
| Maternal height in cm (mean (SD)) | 152.7 (4.7) | 152.7 (4.4) | 0.948 |
| Socioeconomic status indicators | |||
| Bank account, n (%) | 84 (19.0) | 89 (29.6) | 0.001 |
| Television, n (%) | 265 (60.0) | 207 (68.8) | 0.018 |
| Radio, n (%) | 326 (73.8) | 224 (74.4) | 0.907 |
| Cellular telephone, n (%) | 426 (96.4) | 285 (94.7) | 0.350 |
| Maternal education, number of years (mean (SD)) | 9.8 (2.6) | 9.7 (2.8) | 0.701 |
| Number of people living in the house (mean (SD)) | 4.5 (1.7) | 4.6 (1.8) | 0.540 |
| Socioeconomic wealth index (mean (SD)) | 0.4 (0.6) | 0.5 (0.6) | 0.134 |
| Pregnancy factors | |||
| Gestational age, days (mean (SD)) | 275.5 (9.7) | 275.1 (10.1) | 0.552 |
| Nulliparous, n (%) | 164 (37.4) | 116 (38.7) | 0.777 |
| Pre-term birth, n (%) | 17 ( 3.8) | 19 ( 6.3) | 0.173 |
| Minimum dietary diversity | |||
| Low (Less than 4), n (%) | 40 ( 9.0) | 34 (11.3) | 0.380 |
| Medium (4-5), n (%) | 228 (51.6) | 182 (60.5) | 0.021 |
| High (More than 5), n (%) | 174 (39.4) | 85 (28.2) | 0.002 |
| Household food insecurity | |||
| Food secure, n (%) | 247 (56.1) | 139 (47.6) | 0.029 |
| Mild (1–3), n (%) | 144 (32.7) | 110 (37.7) | 0.195 |
| Moderate or severe (4 – 8), n (%) | 49 (11.1) | 43 (14.7) | 0.187 |
| Smoking in the household, n (%) | |||
| Smoking in the household, n (%) | 4 ( 0.9) | 3 ( 1.0) | 1.000 |
| Average personal exposure to fine particulate matter in µg/m3, mean (SD) | |||
| Baseline (mean (SD)) | 92.3 (121.4) | 77.6 (80.3) | 0.092 |
| Prenatal, post-randomization (P1 and P2 visits) (mean (SD)) | 46.8 (97.5) | 41.0 (62.6) | 0.383 |
| Post-natal, post-randomization (B1, B2 and B4 visits) (mean (SD)) | 47.8 (114.6) | 42.8 (106.4) | 0.577 |
| Average personal exposure to carbon monoxide in ppm, mean (SD) | |||
| Baseline (mean (SD)) | 4.1 (6.2) | 3.6 (5.7) | 0.312 |
| Prenatal, post-randomization (P1 and P2 visits) (mean (SD)) | 2.3 (4.3) | 2.0 (3.7) | 0.390 |
| Post-natal, post-randomization (B1, B2 and B4 visits) (mean (SD)) | 4.0 (6.8) | 2.6 (4.1) | 0.004 |
var_label_list <- list(cognitive = "Cognitive", language = "Language", motor = "Motor",
cognitive_perc = "Cognitive", language_perc = "Language", motor_perc = "Motor")
labelled::var_label(df_c2) <- var_label_list
vars <- names(var_label_list)
table3_1 <- CreateTableOne(vars = vars, data = df_c2, factorVars = fvars, testApprox = chisq.test,
argsApprox = list(correct = TRUE), testExact = fisher.test, argsExact = list(workspace = 2 *
10^5), testNormal = oneway.test, argsNormal = list(var.equal = TRUE), testNonNormal = kruskal.test,
argsNonNormal = list(NULL))
table3_2 <- CreateTableOne(vars = vars, strata = "lpg", data = df_c2, factorVars = fvars,
testApprox = chisq.test, argsApprox = list(correct = TRUE), testExact = fisher.test,
argsExact = list(workspace = 2 * 10^5), testNormal = oneway.test, argsNormal = list(var.equal = TRUE),
testNonNormal = kruskal.test, argsNonNormal = list(NULL))
kable3_1 <- print(table3_1, nonnormal = c(), showAllLevels = F, formatOptions = list(big.mark = ","),
explain = T, varLabels = TRUE, printToggle = T, catDigits = 1, contDigits = 1)
kable3_2 <- print(table3_2, nonnormal = c(), showAllLevels = F, formatOptions = list(big.mark = ","),
explain = T, varLabels = TRUE, printToggle = T, catDigits = 1, contDigits = 1)
kable3 <- cbind(kable3_1, kable3_2)
kable3 <- subset(kable3, select = -c(5))| Overall | Control | Intervention | P-value | |
|---|---|---|---|---|
| n | 301 | 136 | 165 | |
| Bayley Scales of Development composite score, mean (SD) | ||||
| Cognitive (mean (SD)) | 90.8 (11.0) | 91.8 (9.8) | 90.1 (11.9) | 0.186 |
| Language (mean (SD)) | 89.0 (10.8) | 90.7 (10.9) | 87.7 (10.5) | 0.017 |
| Motor (mean (SD)) | 95.3 (12.9) | 95.9 (12.2) | 94.8 (13.5) | 0.446 |
| Bayley Scales of Development composite percentile, mean (SD) | ||||
| Cognitive (mean (SD)) | 30.7 (20.2) | 32.0 (19.4) | 29.6 (20.8) | 0.322 |
| Language (mean (SD)) | 27.8 (19.4) | 30.9 (20.6) | 25.1 (18.0) | 0.010 |
| Motor (mean (SD)) | 39.4 (26.4) | 40.4 (25.8) | 38.5 (26.9) | 0.533 |
# Define a function to create the plot
clm_pm_plot <- function(data, outcome_var, ylab) {
# Calculate the means of outcome_var by pmcat
outcome_means <- aggregate(data[[outcome_var]] ~ pmcat, data = data, FUN = mean)
# Create the plot using ggplot
p <- ggplot(outcome_means, aes(x = as.numeric(pmcat), y = `data[[outcome_var]]`)) +
geom_line() +
geom_point(size=2, shape=21, fill="black", colour="white", stroke=3) + # Add points
ylim(80, 105) + # Set y-axis limits
labs(x = "Octiles of PM2.5", y = ylab) + # Set axis labels
scale_x_continuous(breaks = 1:8, labels = round(aggregate(pm ~ pmcat, data = data, FUN = mean)$pm, 1)) +
theme_minimal() # Set plot theme
return(p)
}
# Create the pmcat variable
df_c1$pmcat <- cut(df_c1$pm, breaks = quantile(sort(df_c1$pm), 0:8/8), include.lowest = TRUE, right = TRUE)
# Create plots for cognitive, language, and motor
plot_pm_cognitive <- clm_pm_plot(df_c1, "cognitive", "Cognitive")
plot_pm_language <- clm_pm_plot(df_c1, "language", "Language")
plot_pm_motor <- clm_pm_plot(df_c1, "motor", "Motor")
# Display the plots
plot_pm_cognitive + plot_pm_language + plot_pm_motor# create a function
clm_co_plot <- function(data, outcome_var, ylab) {
# Calculate the means of outcome_var by pmcat
outcome_means <- aggregate(data[[outcome_var]] ~ cocat, data = data, FUN = mean)
# Create the plot using ggplot
p <- ggplot(outcome_means, aes(x = as.numeric(cocat), y = `data[[outcome_var]]`)) +
geom_line() +
geom_point(size=2, shape=21, fill="black", colour="white", stroke=2) + # Add points
ylim(80, 105) + # Set y-axis limits
labs(x = "Octiles of PM2.5", y = ylab) + # Set axis labels
scale_x_continuous(breaks = 1:8, labels = round(aggregate(co ~ cocat, data = data, FUN = mean)$co, 1)) +
theme_minimal() # Set plot theme
return(p)
}
# Create the pmcat and cocat variables
df_c1$cocat <- cut(df_c1$co, breaks = quantile(sort(df_c1$co), 0:8/8), include.lowest = TRUE, right = TRUE)
# Plot for CO
plot_co_cognitive <- clm_co_plot(df_c1, "cognitive", "Cognitive")
plot_co_language <- clm_co_plot(df_c1, "language", "Language")
plot_co_motor <- clm_co_plot(df_c1, "motor", "Motor")
# Display the plots
plot_pm_cognitive + plot_pm_language + plot_pm_motor#library(broom)
# create a function
fit_model1 <- function(outcome) {
model <- lm(outcome ~ lpg + cogdevage + ma0fe1 + sesindex +
anyonesmoke + momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean <- coef(model)[2]
conf_int <- confint(model, level = 1 - 0.05/3)
coef_lb <- conf_int[2, 1]
coef_ub <- conf_int[2, 2]
return(data.frame(mean = coef_mean, lb = coef_lb, ub = coef_ub))
}
# Fit linear regression models for PM exposure
ittpm <- map_dfr(c("cognitive", "language", "motor"), ~ fit_model1(df_c2[[.x]]))
rownames(ittpm) <- c("Cognitive", "Language", "Motor")
kable(ittpm %>%
format(digits = 3), booktabs = TRUE, align = "c", full_width = F,
escape = F) %>%
kable_paper("hover", "striped", full_width = F) | mean | lb | ub | |
|---|---|---|---|
| Cognitive | -1.85 | -4.89 | 1.1967 |
| Language | -2.96 | -5.98 | 0.0712 |
| Motor | -1.42 | -5.05 | 2.2105 |
# Modify data frames for plotting
ittpm_df <- data.frame(
outcome = rownames(ittpm),
mean = ittpm$mean,
lb = ittpm$lb,
ub = ittpm$ub
)
# Reorder the levels of the outcome variable
ittpm_df$outcome <- factor(ittpm_df$outcome, levels = c("Motor", "Language", "Cognitive"))
figure1 <- ggplot(ittpm_df, aes(x = mean, y = outcome, ymin = lb, ymax = ub)) +
geom_point(size = 6, shape = 18, color = "black") +
geom_segment(aes(x = lb, xend = ub, y = outcome, yend = outcome), color = "black") +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 5, y = 3, label = paste0(round(ittpm_df$mean[1], 2), " (", round(ittpm_df$lb[1], 2), " to ", round(ittpm_df$ub[1], 2), ")")) +
annotate("text", x = 5, y = 2, label = paste0(round(ittpm_df$mean[2], 2), " (", round(ittpm_df$lb[2], 2), " to ", round(ittpm_df$ub[2], 2), ")")) +
annotate("text", x = 5, y = 1, label = paste0(round(ittpm_df$mean[3], 2), " (", round(ittpm_df$lb[3], 2), " to ", round(ittpm_df$ub[3], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 14, hjust = 0.5, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Control better", size = 5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Intervention better", size = 5, color = "black")
figure1| Variable | Description |
|---|---|
| erpmall | Data frame containing the regression results of linear models for BSD-III as a function of PM2.5 scaled to |
| the interquartile range adjusted for confounders | |
| ermpm_prepost | Data frame containing the regression results of linear models for for BSD-III as a function of prenatal and |
| post-natal PM2.5 scaled to the interquartile range adjusted for confounders |
# exposure response library(tidyverse) library(dplyr) library(kableExtra)
# Calculate IQR for PM exposure
iqrdiffpm <- quantile(df_c2$pm, c(0.25, 0.75), na.rm = TRUE)
iqrdiffpm_diff <- iqrdiffpm[2] - iqrdiffpm[1]
# Calculate IQR for CO exposure
iqrdiffco <- quantile(df_c2$co, c(0.25, 0.75), na.rm = TRUE)
iqrdiffco_diff <- iqrdiffco[2] - iqrdiffco[1]
# Function to fit linear regression model and extract coefficients and
# confidence intervals
fit_model2 <- function(outcome, exposure, iqr) {
model <- lm(outcome ~ I(exposure/iqr) + cogdevage + ma0fe1 + sesindex + anyonesmoke +
momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean <- coef(model)[2]
conf_int <- confint(model, level = 1 - 0.05/3)
coef_lb <- conf_int[2, 1]
coef_ub <- conf_int[2, 2]
return(data.frame(mean = coef_mean, lb = coef_lb, ub = coef_ub))
}
# Fit linear regression models for PM exposure
erpmall <- map_dfr(c("cognitive", "language", "motor"), ~fit_model2(df_c2[[.x]],
df_c2$pm, iqrdiffpm_diff))
rownames(erpmall) <- c("Cognitive", "Language", "Motor")
kable(erpmall %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F, escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean | lb | ub | |
|---|---|---|---|
| Cognitive | 0.67 | -0.53 | 1.9 |
| Language | 0.45 | -0.75 | 1.7 |
| Motor | 0.44 | -0.99 | 1.9 |
# Fit linear regression models for CO exposure
ercoall <- map_dfr(c("cognitive", "language", "motor"), ~fit_model2(df_c2[[.x]],
df_c2$co, iqrdiffco_diff))
rownames(ercoall) <- c("Cognitive", "Language", "Motor")
kable(ercoall %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F, escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean | lb | ub | |
|---|---|---|---|
| Cognitive | 0.45 | -0.48 | 1.4 |
| Language | 0.27 | -0.66 | 1.2 |
| Motor | 0.38 | -0.74 | 1.5 |
# Calculate IQR for PM_prenatal exposure
iqrdiffpm_prenatal <- quantile(df_c2$prenatalpm, c(0.25, 0.75), na.rm = T)
iqrdiffpm_prenatal_diff <- iqrdiffpm_prenatal[2] - iqrdiffpm_prenatal[1]
# Calculate IQR for PM_postnatal exposure
iqrdiffpm_postnatal <- quantile(df_c2$postnatalpm, c(0.25, 0.75), na.rm = T)
iqrdiffpm_postnatal_diff <- iqrdiffpm_postnatal[2] - iqrdiffpm_postnatal[1]
# Function to fit linear regression model and extract coefficients and
# confidence intervals
fit_model3 <- function(outcome, exposure1, exposure2, iqr1, iqr2) {
model <- lm(outcome ~ I(exposure1/iqr1) + I(exposure2/iqr2) + cogdevage + ma0fe1 +
sesindex + anyonesmoke + momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean_prenatal <- coef(model)[2]
coef_mean_postnatal <- coef(model)[3]
conf_int_prenatal <- confint(model, level = 1 - 0.05/3)
conf_int_postnatal <- confint(model, level = 1 - 0.05/3)
coef_lb_prenatal <- conf_int_prenatal[2, 1]
coef_ub_prenatal <- conf_int_prenatal[2, 2]
coef_lb_postnatal <- conf_int_postnatal[3, 1]
coef_ub_postnatal <- conf_int_postnatal[3, 2]
return(data.frame(mean_prenatal = coef_mean_prenatal, lb_prenatal = coef_lb_prenatal,
ub_prenatal = coef_ub_prenatal, mean_postnatal = coef_mean_postnatal, lb_postnatal = coef_lb_postnatal,
ub_postnatal = coef_ub_postnatal))
}
# Fit linear regression models for PM exposure (pre/postnatal)
erpm_prepost <- map_dfr(c("cognitive", "language", "motor"), ~fit_model3(df_c2[[.x]],
df_c2$prenatalpm, df_c2$postnatalpm, iqrdiffpm_prenatal_diff, iqrdiffpm_postnatal_diff))
rownames(erpm_prepost) <- c("Cognitive", "Language", "Motor")
kable(erpm_prepost %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F, escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean_prenatal | lb_prenatal | ub_prenatal | mean_postnatal | lb_postnatal | ub_postnatal | |
|---|---|---|---|---|---|---|
| Cognitive | 0.52 | -0.63 | 1.7 | 0.012 | -0.19 | 0.21 |
| Language | 0.64 | -0.56 | 1.8 | -0.094 | -0.30 | 0.11 |
| Motor | 0.91 | -0.54 | 2.4 | -0.088 | -0.34 | 0.16 |
# Calculate IQR for Co_prenatal exposure
iqrdiffco_prenatal <- quantile(df_c2$prenatalco, c(0.25, 0.75), na.rm = T)
iqrdiffco_prenatal_diff <- iqrdiffco_prenatal[2] - iqrdiffco_prenatal[1]
# Calculate IQR for CO_postnatal exposure
iqrdiffco_postnatal <- quantile(df_c2$postnatalco, c(0.25, 0.75), na.rm = T)
iqrdiffco_postnatal_diff <- iqrdiffco_postnatal[2] - iqrdiffco_postnatal[1]
# Fit linear regression models for PM exposure (pre/postnatal)
erco_prepost <- map_dfr(c("cognitive", "language", "motor"), ~fit_model3(df_c2[[.x]],
df_c2$prenatalco, df_c2$postnatalco, iqrdiffco_prenatal_diff, iqrdiffco_postnatal_diff))
rownames(erco_prepost) <- c("Cognitive", "Language", "Motor")
kable(erco_prepost %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F, escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean_prenatal | lb_prenatal | ub_prenatal | mean_postnatal | lb_postnatal | ub_postnatal | |
|---|---|---|---|---|---|---|
| Cognitive | 0.399 | -1.06 | 1.9 | 0.515 | -0.76 | 1.8 |
| Language | 0.094 | -1.45 | 1.6 | 0.149 | -1.20 | 1.5 |
| Motor | 0.975 | -0.86 | 2.8 | -0.027 | -1.63 | 1.6 |
erpmall_df <- data.frame(
outcome = rownames(erpmall),
mean = erpmall$mean,
lb = erpmall$lb,
ub = erpmall$ub
)
erpm_prepost_df <- data.frame(
outcome = rownames(erpm_prepost),
mean_prenatal = erpm_prepost$mean_prenatal,
lb_prenatal = erpm_prepost$lb_prenatal,
ub_prenatal = erpm_prepost$ub_prenatal,
mean_postnatal = erpm_prepost$mean_postnatal,
lb_postnatal = erpm_prepost$lb_postnatal,
ub_postnatal = erpm_prepost$ub_postnatal
)
# Reorder the levels of the outcome variable
erpmall_df$outcome <- factor(erpmall_df$outcome, levels = c("Motor", "Language", "Cognitive"))
# Create plot for erpmall
plot2_erpmall <- ggplot(data = erpmall_df, aes(x = mean, y = outcome)) +
geom_point(size = 6, shape = 18) +
geom_errorbarh(aes(xmin = lb, xmax = ub), height = 0, color = "black") +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3, label = paste0(round(erpmall_df$mean[1], 2), " (", round(erpmall_df$lb[1], 2), " to ", round(erpmall_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 2, label = paste0(round(erpmall_df$mean[2], 2), " (", round(erpmall_df$lb[2], 2), " to ", round(erpmall_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 1, label = paste0(round(erpmall_df$mean[3], 2), " (", round(erpmall_df$lb[3], 2), " to ", round(erpmall_df$ub[3], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
ggtitle("A") # Add title A
# Create plot for erpm_prepost
# Create a new column to distinguish between prenatal and postnatal
erpm_prepost_df <- erpm_prepost_df %>%
pivot_longer(cols = -1,
names_to = c(".value", "Type"),
names_sep = "_")
# Reorder the levels of the outcome variable
erpm_prepost_df$outcome <- factor(erpm_prepost_df$outcome, levels = c("Motor", "Language", "Cognitive"))
# Applyplot2_erpm_prepost
plot2_erpm_prepost <- ggplot(erpm_prepost_df, aes(mean, outcome)) +
geom_errorbar(
aes(xmin = lb, xmax = ub, color = Type),
position = position_dodge(0.3), width = 0.2
) +
geom_point(aes(color = Type, shape = Type), size = 4, position = position_dodge(0.42)) +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_color_manual(values = c("prenatal" = "blue", "postnatal" = "red")) +
scale_shape_manual(values = c("prenatal" = 2, "postnatal" = 6)) + # Change shape for each type
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3.1, label = paste0(round(erpm_prepost_df$mean[1], 2), " (", round(erpm_prepost_df$lb[1], 2), " to ", round(erpm_prepost_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 2.9, label = paste0(round(erpm_prepost_df$mean[2], 2), " (", round(erpm_prepost_df$lb[2], 2), " to ", round(erpm_prepost_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 2.1, label = paste0(round(erpm_prepost_df$mean[3], 2), " (", round(erpm_prepost_df$lb[3], 2), " to ", round(erpm_prepost_df$ub[3], 2), ")")) +
annotate("text", x = 4.5, y = 1.9, label = paste0(round(erpm_prepost_df$mean[4], 2), " (", round(erpm_prepost_df$lb[4], 2), " to ", round(erpm_prepost_df$ub[4], 2), ")")) +
annotate("text", x = 4.5, y = 1.1, label = paste0(round(erpm_prepost_df$mean[5], 2), " (", round(erpm_prepost_df$lb[5], 2), " to ", round(erpm_prepost_df$ub[5], 2), ")")) +
annotate("text", x = 4.5, y = 0.9, label = paste0(round(erpm_prepost_df$mean[6], 2), " (", round(erpm_prepost_df$lb[6], 2), " to ", round(erpm_prepost_df$ub[6], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
ggtitle("B") # Add title B
# Plot the three graphs in a matrix
plot2_erpmall + plot2_erpm_prepostercoall_df <- data.frame(
outcome = rownames(ercoall),
mean = ercoall$mean,
lb = ercoall$lb,
ub = ercoall$ub
)
erco_prepost_df <- data.frame(
outcome = rownames(erco_prepost),
mean_prenatal = erco_prepost$mean_prenatal,
lb_prenatal = erco_prepost$lb_prenatal,
ub_prenatal = erco_prepost$ub_prenatal,
mean_postnatal = erco_prepost$mean_postnatal,
lb_postnatal = erco_prepost$lb_postnatal,
ub_postnatal = erco_prepost$ub_postnatal
)
# Reorder the levels of the outcome variable
ercoall_df$outcome <- factor(ercoall_df$outcome, levels = c("Motor", "Language", "Cognitive"))
# Create plot for erpmall
plot3_ercoall <- ggplot(data = ercoall_df, aes(x = mean, y = outcome)) +
geom_point(size = 6, shape = 18) +
geom_errorbarh(aes(xmin = lb, xmax = ub), height = 0, color = "black") +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3, label = paste0(round(ercoall_df$mean[1], 2), " (", round(ercoall_df$lb[1], 2), " to ", round(ercoall_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 2, label = paste0(round(ercoall_df$mean[2], 2), " (", round(ercoall_df$lb[2], 2), " to ", round(ercoall_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 1, label = paste0(round(ercoall_df$mean[3], 2), " (", round(ercoall_df$lb[3], 2), " to ", round(ercoall_df$ub[3], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
ggtitle("A") # Add title A
# Create plot for erpm_prepost
# Create a new column to distinguish between prenatal and postnatal
erco_prepost_df <- erco_prepost_df %>%
pivot_longer(cols = -1,
names_to = c(".value", "Type"),
names_sep = "_")
# Reorder the levels of the outcome variable
erco_prepost_df$outcome <- factor(erco_prepost_df$outcome, levels = c("Motor", "Language", "Cognitive"))
# Applyplot2_erpm_prepost
plot3_erco_prepost <- ggplot(erco_prepost_df, aes(mean, outcome)) +
geom_errorbar(
aes(xmin = lb, xmax = ub, color = Type),
position = position_dodge(0.3), width = 0.2
) +
geom_point(aes(color = Type, shape = Type), size = 4, position = position_dodge(0.42)) +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_color_manual(values = c("prenatal" = "blue", "postnatal" = "red")) +
scale_shape_manual(values = c("prenatal" = 2, "postnatal" = 6)) + # Change shape for each type
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3.1, label = paste0(round(erco_prepost_df$mean[1], 2), " (", round(erco_prepost_df$lb[1], 2), " to ", round(erco_prepost_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 2.9, label = paste0(round(erco_prepost_df$mean[2], 2), " (", round(erco_prepost_df$lb[2], 2), " to ", round(erco_prepost_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 2.1, label = paste0(round(erco_prepost_df$mean[3], 2), " (", round(erco_prepost_df$lb[3], 2), " to ", round(erco_prepost_df$ub[3], 2), ")")) +
annotate("text", x = 4.5, y = 1.9, label = paste0(round(erco_prepost_df$mean[4], 2), " (", round(erco_prepost_df$lb[4], 2), " to ", round(erco_prepost_df$ub[4], 2), ")")) +
annotate("text", x = 4.5, y = 1.1, label = paste0(round(erco_prepost_df$mean[5], 2), " (", round(erco_prepost_df$lb[5], 2), " to ", round(erco_prepost_df$ub[5], 2), ")")) +
annotate("text", x = 4.5, y = 0.9, label = paste0(round(erco_prepost_df$mean[6], 2), " (", round(erco_prepost_df$lb[6], 2), " to ", round(erco_prepost_df$ub[6], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
ggtitle("B") # Add title B
# Plot the three graphs in a matrix
plot3_ercoall + plot3_erco_prepost# Fit linear regression models for PM exposure with logarithmic scale
fit_model2_log <- function(outcome, exposure, iqr) {
model <- lm(outcome ~ I(log(exposure / iqr)) + cogdevage + ma0fe1 + sesindex + anyonesmoke + momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean <- coef(model)[2]
conf_int <- confint(model, level = 1 - 0.05/3)
coef_lb <- conf_int[2, 1]
coef_ub <- conf_int[2, 2]
return(data.frame(mean = coef_mean, lb = coef_lb, ub = coef_ub))
}
# Fit linear regression models for PM exposure with logarithmic scale
erpmall_log <- map_dfr(c("cognitive", "language", "motor"), ~ fit_model2_log(df_c2[[.x]], df_c2$pm, iqrdiffpm_diff))
rownames(erpmall_log) <- c("Cognitive", "Language", "Motor")
kable(erpmall_log %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F,
escape = F) %>%
kable_paper("hover", "striped", full_width = F) | mean | lb | ub | |
|---|---|---|---|
| Cognitive | 1.3 | -0.82 | 3.4 |
| Language | 1.4 | -0.65 | 3.5 |
| Motor | 1.3 | -1.24 | 3.8 |
erpmall_log_df <- data.frame(
outcome = rownames(erpmall_log),
mean_log = as.numeric(erpmall_log$mean),
lb_log = as.numeric(erpmall_log$lb),
ub_log = as.numeric(erpmall_log$ub)
)
# Reorder the levels of the outcome variable
erpmall_log_df <- erpmall_log_df %>%
mutate(outcome = factor(outcome, levels = c("Motor", "Language", "Cognitive")))
# Create plot for erpmall with logarithmic scale
plot4_erpmall_log <- ggplot(data = erpmall_log_df, aes(x = mean_log, y = outcome)) +
geom_point(size = 6, shape = 18) +
geom_errorbarh(aes(xmin = lb_log, xmax = ub_log), height = 0, color = "black") +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "Difference in scores", y = NULL) +
coord_cartesian(ylim = c(1.2, 3.5)) + # Adjust y-axis limits
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("text", x = 4.5, y = 3.1, label = paste0(round(erpmall_log_df$mean_log[1], 2), " (", round(erpmall_log_df$lb_log[1], 2), " to ", round(erpmall_log_df$ub_log[1], 2), ")")) +
annotate("text", x = 4.5, y = 2.1, label = paste0(round(erpmall_log_df$mean_log[2], 2), " (", round(erpmall_log_df$lb_log[2], 2), " to ", round(erpmall_log_df$ub_log[2], 2), ")")) +
annotate("text", x = 4.5, y = 1.1, label = paste0(round(erpmall_log_df$mean_log[3], 2), " (", round(erpmall_log_df$lb_log[3], 2), " to ", round(erpmall_log_df$ub_log[3], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
xlim(-6, 6) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
ggtitle("A") # Add title A
# Fit linear regression models for PM exposure with logarithmic scale
fit_model3_log <- function(outcome, exposure1, exposure2, iqr1, iqr2) {
model <- lm(outcome ~ I(log(exposure1 / iqr1)) + I(log(exposure2 / iqr2)) + cogdevage + ma0fe1 + sesindex + anyonesmoke + momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean_prenatal <- coef(model)[2]
coef_mean_postnatal <- coef(model)[3]
conf_int_prenatal <- confint(model, level = 1 - 0.05/3)
conf_int_postnatal <- confint(model, level = 1 - 0.05/3)
coef_lb_prenatal <- conf_int_prenatal[2, 1]
coef_ub_prenatal <- conf_int_prenatal[2, 2]
coef_lb_postnatal <- conf_int_postnatal[3, 1]
coef_ub_postnatal <- conf_int_postnatal[3, 2]
return(data.frame(mean_prenatal = coef_mean_prenatal, lb_prenatal = coef_lb_prenatal, ub_prenatal = coef_ub_prenatal,
mean_postnatal = coef_mean_postnatal, lb_postnatal = coef_lb_postnatal, ub_postnatal = coef_ub_postnatal))
}
# Fit linear regression models for PM exposure (pre/postnatal)
erpm_prepost_log <- map_dfr(c("cognitive", "language", "motor"), ~ fit_model3_log(df_c2[[.x]], df_c2$prenatalpm, df_c2$postnatalpm,iqrdiffpm_prenatal_diff, iqrdiffpm_postnatal_diff))
rownames(erpm_prepost_log) <- c("Cognitive", "Language", "Motor")
kable(erpm_prepost_log %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F,
escape = F) %>%
kable_paper("hover", "striped", full_width = F) | mean_prenatal | lb_prenatal | ub_prenatal | mean_postnatal | lb_postnatal | ub_postnatal | |
|---|---|---|---|---|---|---|
| Cognitive | 1.2 | -0.73 | 3.2 | 0.072 | -1.8 | 1.9 |
| Language | 1.5 | -0.63 | 3.5 | -0.176 | -2.1 | 1.8 |
| Motor | 2.1 | -0.40 | 4.6 | -1.260 | -3.6 | 1.1 |
erpm_prepost_log_df <- data.frame(
outcome = rownames(erpm_prepost_log),
mean_prenatal_log = as.numeric(erpm_prepost_log$mean_prenatal),
lb_prenatal_log = as.numeric(erpm_prepost_log$lb_prenatal),
ub_prenatal_log = as.numeric(erpm_prepost_log$ub_prenatal),
mean_postnatal_log = as.numeric(erpm_prepost_log$mean_postnatal),
lb_postnatal_log = as.numeric(erpm_prepost_log$lb_postnatal),
ub_postnatal_log = as.numeric(erpm_prepost_log$ub_postnatal)
)
# Create a new column to distinguish between prenatal and postnatal
erpm_prepost_log_df <- erpm_prepost_log_df %>%
pivot_longer(cols = -1,
names_to = c(".value", "Type"),
names_sep = "_")
# Reorder the levels of the outcome variable
erpm_prepost_log_df <- erpm_prepost_log_df %>%
mutate(outcome = factor(outcome, levels = c("Motor", "Language", "Cognitive")))
# Create plot for erpm_prepost with logarithmic scale
plot4_erpm_prepost_log_df <- ggplot(erpm_prepost_log_df, aes(mean, outcome)) +
geom_errorbar(
aes(xmin = lb, xmax = ub, color = Type),
position = position_dodge(0.3), width = 0.2
) +
geom_point(aes(color = Type, shape = Type), size = 4, position = position_dodge(0.42)) +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_color_manual(values = c("prenatal" = "blue", "postnatal" = "red")) +
scale_shape_manual(values = c("prenatal" = 2, "postnatal" = 6)) + # Change shape for each type
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3.2, label = paste0(round(erpm_prepost_log_df$mean[1], 2), " (", round(erpm_prepost_log_df$lb[1], 2), " to ", round(erpm_prepost_log_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 3, label = paste0(round(erpm_prepost_log_df$mean[2], 2), " (", round(erpm_prepost_log_df$lb[2], 2), " to ", round(erpm_prepost_log_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 2.2, label = paste0(round(erpm_prepost_log_df$mean[3], 2), " (", round(erpm_prepost_log_df$lb[3], 2), " to ", round(erpm_prepost_log_df$ub[3], 2), ")")) +
annotate("text", x = 4.5, y = 2, label = paste0(round(erpm_prepost_log_df$mean[4], 2), " (", round(erpm_prepost_log_df$lb[4], 2), " to ", round(erpm_prepost_log_df$ub[4], 2), ")")) +
annotate("text", x = 4.5, y = 1.2, label = paste0(round(erpm_prepost_log_df$mean[5], 2), " (", round(erpm_prepost_log_df$lb[5], 2), " to ", round(erpm_prepost_log_df$ub[5], 2), ")")) +
annotate("text", x = 4.5, y = 1, label = paste0(round(erpm_prepost_log_df$mean[6], 2), " (", round(erpm_prepost_log_df$lb[6], 2), " to ", round(erpm_prepost_log_df$ub[6], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.5 is worse", size = 4.5, color = "black") +
ggtitle("B") # Add title A
# View the plot
plot4_erpmall_log + plot4_erpm_prepost_log_df# Fit linear regression models for PM exposure with logarithmic scale
ercoall_log <- map_dfr(c("cognitive", "language", "motor"), ~ fit_model2_log(df_c2[[.x]], as.numeric(df_c2$co+0.005), iqrdiffco_diff))
rownames(ercoall_log) <- c("Cognitive", "Language", "Motor")
kable(ercoall_log %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F,
escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean | lb | ub | |
|---|---|---|---|
| Cognitive | 0.57 | -0.83 | 2.0 |
| Language | 0.70 | -0.70 | 2.1 |
| Motor | 0.91 | -0.76 | 2.6 |
ercoall_log_df <- data.frame(
outcome = rownames(ercoall_log),
mean_log = as.numeric(ercoall_log$mean),
lb_log = as.numeric(ercoall_log$lb),
ub_log = as.numeric(ercoall_log$ub)
)
# Reorder the levels of the outcome variable
ercoall_log_df <- ercoall_log_df %>%
mutate(outcome = factor(outcome, levels = c("Motor", "Language", "Cognitive")))
# Create plot for erpmall with logarithmic scale
plot5_ercoall_log <- ggplot(data = ercoall_log_df, aes(x = mean_log, y = outcome)) +
geom_point(size = 6, shape = 18) +
geom_errorbarh(aes(xmin = lb_log, xmax = ub_log), height = 0, color = "black") +
geom_vline(xintercept = 0, linetype = "dashed") +
labs(x = "Difference in scores", y = NULL) +
coord_cartesian(ylim = c(1.2, 3.5)) + # Adjust y-axis limits
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("text", x = 4.5, y = 3.1, label = paste0(round(ercoall_log_df$mean_log[1], 2), " (", round(ercoall_log_df$lb_log[1], 2), " to ", round(ercoall_log_df$ub_log[1], 2), ")")) +
annotate("text", x = 4.5, y = 2.1, label = paste0(round(ercoall_log_df$mean_log[2], 2), " (", round(ercoall_log_df$lb_log[2], 2), " to ", round(ercoall_log_df$ub_log[2], 2), ")")) +
annotate("text", x = 4.5, y = 1.1, label = paste0(round(ercoall_log_df$mean_log[3], 2), " (", round(ercoall_log_df$lb_log[3], 2), " to ", round(ercoall_log_df$ub_log[3], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
ggtitle("A") # Add title A
# Fit linear regression models for PM exposure with logarithmic scale
fit_model3_log <- function(outcome, exposure1, exposure2, iqr1, iqr2) {
model <- lm(outcome ~ I(log(exposure1 / iqr1)) + I(log(exposure2 / iqr2)) + cogdevage + ma0fe1 + sesindex + anyonesmoke + momage + momeduc + momheight + mdds + preterm, data = df_c2)
coef_mean_prenatal <- coef(model)[2]
coef_mean_postnatal <- coef(model)[3]
conf_int_prenatal <- confint(model, level = 1 - 0.05/3)
conf_int_postnatal <- confint(model, level = 1 - 0.05/3)
coef_lb_prenatal <- conf_int_prenatal[2, 1]
coef_ub_prenatal <- conf_int_prenatal[2, 2]
coef_lb_postnatal <- conf_int_postnatal[3, 1]
coef_ub_postnatal <- conf_int_postnatal[3, 2]
return(data.frame(mean_prenatal = coef_mean_prenatal, lb_prenatal = coef_lb_prenatal, ub_prenatal = coef_ub_prenatal,
mean_postnatal = coef_mean_postnatal, lb_postnatal = coef_lb_postnatal, ub_postnatal = coef_ub_postnatal))
}
# Fit linear regression models for PM exposure (pre/postnatal)
erco_prepost_log <- map_dfr(c("cognitive", "language", "motor"), ~ fit_model3_log(df_c2[[.x]], as.numeric(df_c2$prenatalco+0.005), as.numeric(df_c2$postnatalco+0.005),iqrdiffco_prenatal_diff, iqrdiffco_postnatal_diff))
rownames(erco_prepost_log) <- c("Cognitive", "Language", "Motor")
kable(erco_prepost_log %>%
format(digits = 2), booktabs = TRUE, align = "c", full_width = F,
escape = F) %>%
kable_paper("hover", "striped", full_width = F)| mean_prenatal | lb_prenatal | ub_prenatal | mean_postnatal | lb_postnatal | ub_postnatal | |
|---|---|---|---|---|---|---|
| Cognitive | 0.16 | -1.21 | 1.5 | 0.18 | -0.67 | 1.03 |
| Language | 0.62 | -0.83 | 2.1 | 0.18 | -0.71 | 1.07 |
| Motor | 1.31 | -0.38 | 3.0 | -0.30 | -1.36 | 0.76 |
erco_prepost_log_df <- data.frame(
outcome = rownames(erco_prepost_log),
mean_prenatal_log = as.numeric(erco_prepost_log$mean_prenatal),
lb_prenatal_log = as.numeric(erco_prepost_log$lb_prenatal),
ub_prenatal_log = as.numeric(erco_prepost_log$ub_prenatal),
mean_postnatal_log = as.numeric(erco_prepost_log$mean_postnatal),
lb_postnatal_log = as.numeric(erco_prepost_log$lb_postnatal),
ub_postnatal_log = as.numeric(erco_prepost_log$ub_postnatal)
)
# Create a new column to distinguish between prenatal and postnatal
erco_prepost_log_df <- erco_prepost_log_df %>%
pivot_longer(cols = -1,
names_to = c(".value", "Type"),
names_sep = "_")
# Reorder the levels of the outcome variable
erco_prepost_log_df <- erco_prepost_log_df %>%
mutate(outcome = factor(outcome, levels = c("Motor", "Language", "Cognitive")))
# Create plot for erpm_prepost with logarithmic scale
plot5_erco_prepost_log_df <- ggplot(erco_prepost_log_df, aes(mean, outcome)) +
geom_errorbar(
aes(xmin = lb, xmax = ub, color = Type),
position = position_dodge(0.3), width = 0.2
) +
geom_point(aes(color = Type, shape = Type), size = 4, position = position_dodge(0.4)) +
geom_vline(xintercept = 0, linetype = "dashed") +
scale_color_manual(values = c("prenatal" = "blue", "postnatal" = "red")) +
scale_shape_manual(values = c("prenatal" = 2, "postnatal" = 6)) + # Change shape for each type
labs(x = "Difference in scores", y = NULL) +
annotate("text", x = 4.5, y = 3.2, label = paste0(round(erco_prepost_log_df$mean[1], 2), " (", round(erco_prepost_log_df$lb[1], 2), " to ", round(erco_prepost_log_df$ub[1], 2), ")")) +
annotate("text", x = 4.5, y = 3, label = paste0(round(erco_prepost_log_df$mean[2], 2), " (", round(erco_prepost_log_df$lb[2], 2), " to ", round(erco_prepost_log_df$ub[2], 2), ")")) +
annotate("text", x = 4.5, y = 2.2, label = paste0(round(erco_prepost_log_df$mean[3], 2), " (", round(erco_prepost_log_df$lb[3], 2), " to ", round(erco_prepost_log_df$ub[3], 2), ")")) +
annotate("text", x = 4.5, y = 2, label = paste0(round(erco_prepost_log_df$mean[4], 2), " (", round(erco_prepost_log_df$lb[4], 2), " to ", round(erco_prepost_log_df$ub[4], 2), ")")) +
annotate("text", x = 4.5, y = 1.2, label = paste0(round(erco_prepost_log_df$mean[5], 2), " (", round(erco_prepost_log_df$lb[5], 2), " to ", round(erco_prepost_log_df$ub[5], 2), ")")) +
annotate("text", x = 4.5, y = 1, label = paste0(round(erco_prepost_log_df$mean[6], 2), " (", round(erco_prepost_log_df$lb[6], 2), " to ", round(erco_prepost_log_df$ub[6], 2), ")")) +
coord_cartesian(ylim = c(0.5, 3)) + # Adjust y-axis limits
scale_x_continuous(labels = function(x) sprintf("%.f", x), breaks = seq(-6, 6, by = 1), limits = c(-6, 6)) +
theme_linedraw() +
scale_x_continuous(guide = "axis_minor", breaks = seq(-6, 6, by = 1), minor_breaks = scales::breaks_width(0.1)) +
theme(plot.title = element_text(size = 32, hjust = 0, vjust = 2),
legend.text = element_text(size = 12),
axis.text = element_text(size = 12), # Adjust size of axis text
axis.title = element_text(size = 15),
axis.ticks.length = unit(5, "pt"),
axis.minor.ticks.length = rel(0.5),
axis.minor.ticks.x.bottom = element_line(colour = 'black')) +
annotate("segment", x = -1, xend = -6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"), color = "black") +
annotate("text", x = -3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
annotate("segment", x = 1, xend = 6, y = 0.5, yend = 0.5, arrow = arrow(type = "closed"), length = unit(0.2, "inches"),color = "black") +
annotate("text", x = 3, y = 0.4, label = "Higher PM2.6 is worse", size = 4.5, color = "black") +
ggtitle("B") # Add title B
# View the plot
plot5_ercoall_log + plot5_erco_prepost_log_df