library(dplyr)
library(tidyr)
library(ggplot2)
library(languageR)
library(lme4)
library(emmeans)
library(lmerTest)

loading the data

all.select <- read.csv("all.select.csv", check.names = FALSE)
all.select <- all.select %>% select(-any_of("X"))

Number of participants

# Number of participants from each language
all.select %>%
        filter(!is.na(target)) %>%
        group_by(participant) %>%
        slice_head() %>%
        group_by(lang) %>%
        summarise(n()) 
## # A tibble: 5 × 2
##   lang      `n()`
##   <chr>     <int>
## 1 german       21
## 2 hungarian    20
## 3 malayalam    16
## 4 mandarin     22
## 5 yoruba       12
# total number of participants
all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  summarise(n()) 
##   n()
## 1  91

Age of participants

# making sure that the values in age.in.mo column are all numeric
all.select$age.in.mo<- as.numeric(all.select$age.in.mo)

# mean and standard deviation of age of participants in month
all.select %>%
        group_by(participant) %>%
        slice_head() %>%
        group_by(lang) %>%
        summarise(mean(age.in.mo), sd(age.in.mo))
## # A tibble: 5 × 3
##   lang      `mean(age.in.mo)` `sd(age.in.mo)`
##   <chr>                 <dbl>           <dbl>
## 1 german                 61.9            8.43
## 2 hungarian              55.4            2.46
## 3 malayalam              54.8            2.76
## 4 mandarin               68.9            3.48
## 5 yoruba                 61.3           11.4

checking whether there are statistically significant differences between languages

deu.age <- all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  filter(lang == "german") %>%
        select(age.in.mo) 

hun.age <- all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  filter(lang == "hungarian") %>%
        select(age.in.mo) 

mal.age  <- all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  filter(lang == "malayalam") %>%
        select(age.in.mo) 

cmn.age  <- all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  filter(lang == "mandarin") %>%
        select(age.in.mo) 

yor.age  <- all.select %>%
  filter(!is.na(target)) %>%
  filter(item.order == 1) %>%
  filter(lang == "yoruba") %>%
        select(age.in.mo) 

# making sure that the age in months are all integers
hun.age$age.in.mo <- as.integer(hun.age$age.in.mo)
deu.age$age.in.mo <- as.integer(deu.age$age.in.mo)
mal.age$age.in.mo <- as.integer(mal.age$age.in.mo)
cmn.age$age.in.mo <- as.integer(cmn.age$age.in.mo)
yor.age$age.in.mo <- as.integer(yor.age$age.in.mo)
#alpha
0.05/10
## [1] 0.005
t.test(hun.age$age.in.mo, deu.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  hun.age$age.in.mo and deu.age$age.in.mo
## t = -3.3612, df = 23.536, p-value = 0.002641
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -10.422316  -2.487208
## sample estimates:
## mean of x mean of y 
##  55.45000  61.90476
t.test(mal.age$age.in.mo, deu.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  mal.age$age.in.mo and deu.age$age.in.mo
## t = -3.6089, df = 25.36, p-value = 0.001321
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -11.13679  -3.04773
## sample estimates:
## mean of x mean of y 
##  54.81250  61.90476
t.test(cmn.age$age.in.mo, deu.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  cmn.age$age.in.mo and deu.age$age.in.mo
## t = 3.5075, df = 26.376, p-value = 0.00164
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##   2.883494 11.034255
## sample estimates:
## mean of x mean of y 
##  68.86364  61.90476
t.test(yor.age$age.in.mo, deu.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  yor.age$age.in.mo and deu.age$age.in.mo
## t = -0.15176, df = 18.008, p-value = 0.8811
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -8.481969  7.339112
## sample estimates:
## mean of x mean of y 
##  61.33333  61.90476
t.test(hun.age$age.in.mo, mal.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  hun.age$age.in.mo and mal.age$age.in.mo
## t = 0.72214, df = 30.408, p-value = 0.4757
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -1.16439  2.43939
## sample estimates:
## mean of x mean of y 
##   55.4500   54.8125
t.test(hun.age$age.in.mo, yor.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  hun.age$age.in.mo and yor.age$age.in.mo
## t = -1.7662, df = 11.62, p-value = 0.1036
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -13.167329   1.400662
## sample estimates:
## mean of x mean of y 
##  55.45000  61.33333
t.test(hun.age$age.in.mo, cmn.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  hun.age$age.in.mo and cmn.age$age.in.mo
## t = -14.519, df = 37.796, p-value < 2.2e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -15.28428 -11.54300
## sample estimates:
## mean of x mean of y 
##  55.45000  68.86364
t.test(mal.age$age.in.mo, cmn.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  mal.age$age.in.mo and cmn.age$age.in.mo
## t = -13.859, df = 35.673, p-value = 6.268e-16
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -16.10797 -11.99430
## sample estimates:
## mean of x mean of y 
##  54.81250  68.86364
t.test(mal.age$age.in.mo, yor.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  mal.age$age.in.mo and yor.age$age.in.mo
## t = -1.9424, df = 11.976, p-value = 0.07597
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##  -13.8368141   0.7951474
## sample estimates:
## mean of x mean of y 
##  54.81250  61.33333
t.test(cmn.age$age.in.mo, yor.age$age.in.mo)
## 
##  Welch Two Sample t-test
## 
## data:  cmn.age$age.in.mo and yor.age$age.in.mo
## t = 2.2358, df = 12.135, p-value = 0.04491
## alternative hypothesis: true difference in means is not equal to 0
## 95 percent confidence interval:
##   0.2009468 14.8596592
## sample estimates:
## mean of x mean of y 
##  68.86364  61.33333
all.ages <- all.select %>%
        group_by(participant) %>%
        slice_head() %>%
        select(participant, age.in.mo, lang)

# Distribution of children based on their age in month and language

ggplot(all.ages, aes(x = age.in.mo, fill = lang)) +
  geom_density(alpha = 0.4) + # Alpha makes the colors transparent so they overlap
  theme_minimal() +
  labs(title = "Age Distribution by Language",
       x = "Age",
       y = "Density")

Proportion of target responses

We coded a production target = 1 when

    - the language is an obligatory wh-ex-situ language, the wh-phrase is produced clause-initially
    - the language is an wh-in-situ language, and the wh-phrase is produced in-situ
    - the correct wh-phrase (in nominative or accusative, when applicable) is produced
    - the verb is in active, rather than in passive mood
    - the extraction site was correct (judged by the position of the gap)
    - full DP was used instead of a pronoun, or a null argument
    - there is a gap
    

We coded a production correct (adult-like alternative structure) = 1 when

    - the produced form retains the meaning of the target question and
    - the produced form contains the following structure
    - passive
    - cleft
    - topicalization
    - use of pronoun for the non-wh-phrase argument, both overt and covert
    - dislocation (e.g., topicalization)
            
            

table 3

Overall number and percentage of target and adult-like production Separated by the wh-type and argument type per language

overall <- all.select %>%
        filter(wh.type != "whatQ") %>%
        group_by(lang, argument.type, wh.type) %>%
        filter(!is.na(argument.type)) %>%
        summarise(n=n(), sum.target = sum(target), pertarget = sum.target/n, sum.correct = sum(correct), percorrect = sum.correct/n, gram = sum(grammatical), pergram = gram/n)
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, argument.type, and wh.type.
## ℹ Output is grouped by lang and argument.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type, wh.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.
coded.data <- all.select %>%
        mutate(others = case_when(case.obj == 1 ~ 1,
                                  case.subj == 1 ~ 1,
                                  numeral == 1 ~ 1,
                                  subj.num == 1 ~ 1,
                                  extra.demo == 1 ~ 1,
                                  other.error == 1 ~ 1,
                                  other.grammar == 1 ~ 1,
                                  other.v == 1 ~ 1,
                                  tense.aspect == 1 ~ 1,
                                  verb.num == 1 ~ 1,
                                  topic == 1 ~ 1,
                                  dislocation == 1 ~ 1,
                                  gender == 1 ~ 1,
                                  TRUE ~ 0)) 
write.csv(coded.data, "coded.data.csv")
w <- coded.data %>%
        mutate(category = case_when(
                grammatical == 0 ~ "ungrammatical",
                role.inversion == 1 ~ "role reversal",
                (correct == 0 & wrong.wh == 1) ~ "wrong wh (incorrect)",
                correct == 0 ~ "other errors",
                correct == 1 & passives == 1 ~ "passive",
                correct == 1 & covert.pro == 1 ~ "null pro",
                correct == 1 & overt.pro == 1 ~ "overt pro",
                correct == 1 & cleft == 1 ~ "cleft",
                correct == 1 & drop.after.which == 1 ~ "bare which",
                correct == 1 & wrong.wh == 1 ~ "wrong wh",
                correct == 1 & extra.demo == 1 ~ "target",
                others == 1 ~ "others",
                TRUE ~ "target"
                )) 


w$category <- factor(w$category, levels = c("ungrammatical", "role reversal","wrong wh (incorrect)", "other errors", "others", "passive", "null pro", "overt pro", "cleft", "bare which", "wrong wh","target"))
w$argument.type <- factor(w$argument.type, levels = c("subject", "object"))
w$item.type <- factor(w$item.type, levels = c("whoS", "whoO", "whichS", "whichO", "whatO"))

for the figures in Figure 3 and 4: in order to get percentages of use of each type of construction, we identify the number of items per language

all.select %>%
        group_by(lang, item.type, argument.type) %>%
        summarise(n()) %>%
        print(n = 25)
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, item.type, and argument.type.
## ℹ Output is grouped by lang and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, item.type, argument.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.
# One item each from which-subject and which-object questions was ambiguous in German. Because of this, we separate the which-questions from who-questions and what-questions for just German.
german.itemized1 <- w %>%
        filter(lang == "german") %>%
        filter(item.type == "whichO" | item.type == "whichS") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/105)%>%
        mutate(ll = "german")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
german.itemized2 <- w %>%
        filter(lang == "german") %>%
        filter(item.type == "whoS" | item.type == "whoO" | item.type == "whatO") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/126)%>%
        mutate(ll = "german")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
hungarian.itemized <- w %>%
        filter(lang == "hungarian") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/120)%>%
        mutate(ll = "hungarian")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
malayalam.itemized <- w %>%
        filter(lang == "malayalam") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/96)%>%
        mutate(ll = "malayalam")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
mandarin.itemized <- w %>%
        filter(lang == "mandarin") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/132)%>%
        mutate(ll = "mandarin")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
yoruba.itemized <- w %>%
        filter(lang == "yoruba") %>%
        group_by(argument.type, item.type, category) %>%
        summarise(number = n()/72) %>%
        mutate(ll = "yoruba")
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by argument.type, item.type, and category.
## ℹ Output is grouped by argument.type and item.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(argument.type, item.type, category))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.

putting all the languages together

w.all <- rbind(german.itemized1,german.itemized2, hungarian.itemized, malayalam.itemized, mandarin.itemized, yoruba.itemized)

separating target + adult-like alternatives (blue/green) and non-adult-like (red)

we create a variable “non.adult.like” in order to separate the errors that are not adult-like from adult-like produced forms

w.all <- w.all %>%
        mutate(not.adult.like = case_when(
                category == "ungrammatical" ~ 1,
                category == "wrong wh (incorrect)" ~ 1,
                category == "other errors" ~ 1,
                category == "role reversal" ~ 1,
                TRUE ~ 0))

Figure 3: proportion of adult-like forms (categorized)

w.all %>%
        filter(not.adult.like == 0) %>%
        ggplot(aes(x = item.type, y = number, fill = category)) +
        geom_bar(position="stack", stat = "identity") +
        scale_fill_manual(values =c("darkolivegreen","chartreuse3","darkolivegreen2", "lightgreen", "darkslategray3", "deepskyblue","cornflowerblue","darkblue")) + 
        #scale_fill_manual(values = gray.colors(8)) +
        facet_wrap(~ll) + 
        xlab("type of wh-question") + ylab("proportion of occurrences") + ggtitle("Proportion of types of forms produced per language") +
 guides(fill = guide_legend(title = "type of responses")) +
theme(
    plot.title = element_text(size = 18), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    axis.text.x = element_text(angle=90, hjust=1, vjust=0.5, size=12),
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 15)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))

Figure 3: in gray scale

w.all %>%
        filter(not.adult.like == 0) %>%
        ggplot(aes(x = item.type, y = number, fill = category)) +
        geom_bar(position="stack", stat = "identity") +
        scale_fill_grey(start = .9, end = .1) +
        facet_wrap(~ll) + 
        xlab("type of wh-question") + ylab("proportion of occurrences") + ggtitle("Proportion of types of forms produced per language") +
 guides(fill = guide_legend(title = "type of responses")) +
theme(
    plot.title = element_text(size = 18), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    axis.text.x = element_text(angle=90, hjust=1, vjust=0.5, size=12),
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 15)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))

Figure 4: proportion of errors (categorized)

w.all %>%
        filter(not.adult.like == 1) %>%
        ggplot(aes(x = item.type, y = number, fill = category)) +
        geom_bar(position="stack", stat = "identity") +
        facet_wrap(~ll) +
        scale_fill_manual(values =c("red", "orange","brown3","pink"))+
        #scale_fill_manual(values = gray.colors(4)) +
        xlab("type of wh-question") + ylab("proportion of occurrences") + ggtitle("Proportion of types of errors per language") +
        ylim(0,1) +
 guides(fill = guide_legend(title = "type of responses")) +
theme(
    plot.title = element_text(size = 18), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    axis.text.x = element_text(angle=90, hjust=1, vjust=0.5, size=12),
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 15)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))

Detecting the expected asymmetries

box plots with scatter plots as overlay

Figure 5: target wh-questions

all.select$item.type <- factor(all.select$item.type, c("whoS", "whoO", "whichS", "whichO", "whatO"))

all.select %>%
        filter(wh.type != "whatQ") %>%
        filter(lang != "malayalam") %>%
        group_by(lang, participant, item.type) %>%
        summarise(n(), tar.n = sum(target)) %>%
        ggplot(aes(x = item.type, y = tar.n, fill = item.type)) +
  # 1. The Boxplot Layer
  geom_boxplot(outlier.shape = NA, alpha = 0.5) + 
  # 2. The Scatter Plot Overlay
  geom_jitter(width = 0.2, color = "black", alpha = 0.4) +
        facet_wrap(~lang) +
        #scale_fill_viridis_d(option = "viridis") +  # 'd' for discrete data
  scale_fill_brewer(palette = "Dark2") +
  theme_minimal()+
  labs(
    #fill = "Type of Wh-phrases", # Changes the legend title
    x = "Wh-phrases",        # Changes X-axis label
    y = "Distribution of participants"          # Changes Y-axis label
  ) +
  theme(legend.position = "none") + # This line deletes the legend 
  theme(
    plot.title = element_text(size = 18, face = "bold"), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 14)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, participant, and item.type.
## ℹ Output is grouped by lang and participant.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, participant, item.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.

Figure 5-gray: target wh-questions

all.select$item.type <- factor(all.select$item.type, c("whoS", "whoO", "whichS", "whichO", "whatO"))

all.select %>%
        filter(wh.type != "whatQ") %>%
        filter(lang != "malayalam") %>%
        group_by(lang, participant, item.type) %>%
        summarise(n(), tar.n = sum(target)) %>%
        ggplot(aes(x = item.type, y = tar.n, fill = item.type)) +
  # 1. The Boxplot Layer
  geom_boxplot(outlier.shape = NA, alpha = 0.5) + 
  # 2. The Scatter Plot Overlay
  geom_jitter(width = 0.2, color = "black", alpha = 0.4) +
        facet_wrap(~lang) +
        #scale_fill_viridis_d(option = "viridis") +  # 'd' for discrete data
  scale_fill_grey(start = 0, end = .9)+
  theme_minimal()+
  labs(
    #fill = "Type of Wh-phrases", # Changes the legend title
    x = "Wh-phrases",        # Changes X-axis label
    y = "Distribution of participants"          # Changes Y-axis label
  ) +
  theme(legend.position = "none") + # This line deletes the legend 
  theme(
    plot.title = element_text(size = 18, face = "bold"), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 14)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, participant, and item.type.
## ℹ Output is grouped by lang and participant.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, participant, item.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.

Figure 6: adult-like forms (including target)

all.select %>%
        filter(wh.type != "whatQ") %>%
        group_by(lang, participant, item.type) %>%
        summarise(n(), cor.n = sum(correct)) %>%
        ggplot(aes(x = item.type, y = cor.n, fill = item.type)) +
  # 1. The Boxplot Layer
  geom_boxplot(outlier.shape = NA, alpha = 0.5) + 
  # 2. The Scatter Plot Overlay
  geom_jitter(width = 0.2, color = "black", alpha = 0.4) +
        facet_wrap(~lang) +
 scale_fill_brewer(palette = "Dark2") + 
        #scale_fill_grey(start = 0, end = .9)+
  theme_minimal()+
  labs(
    fill = "Type of Wh-phrases", # Changes the legend title
    x = "Wh-phrases",        # Changes X-axis label
    y = "Distribution of participants"          # Changes Y-axis label
  ) +
  theme(legend.position = "none") + # This line deletes the legend 
  theme(
    plot.title = element_text(size = 18, face = "bold"), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 11),                # The numbers/labels on axes
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 14)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, participant, and item.type.
## ℹ Output is grouped by lang and participant.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, participant, item.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.

Figure 6-gray: adult-like forms (including target)

all.select %>%
        filter(wh.type != "whatQ") %>%
        group_by(lang, participant, item.type) %>%
        summarise(n(), cor.n = sum(correct)) %>%
        ggplot(aes(x = item.type, y = cor.n, fill = item.type)) +
  # 1. The Boxplot Layer
  geom_boxplot(outlier.shape = NA, alpha = 0.5) + 
  # 2. The Scatter Plot Overlay
  geom_jitter(width = 0.2, color = "black", alpha = 0.7) +
        facet_wrap(~lang) +
        scale_fill_grey(start = 0, end = .9)+
  theme_minimal()+
  labs(
    fill = "Type of Wh-phrases", # Changes the legend title
    x = "Wh-phrases",        # Changes X-axis label
    y = "Distribution of participants"          # Changes Y-axis label
  ) +
  theme(legend.position = "none") + # This line deletes the legend 
  theme(
    plot.title = element_text(size = 18, face = "bold"), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 11),                # The numbers/labels on axes
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
    strip.text = element_text(size = 14)                # Font size of Facet labels
  )+
  theme(
    # This targets the 'big category' labels specifically
    strip.text = element_text(size = 14, face = "bold"))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, participant, and item.type.
## ℹ Output is grouped by lang and participant.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, participant, item.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.

Statistical analysis

analysis to check whether subject > object holds for both who and which questions (per language)

We fitted models, using the generalized mixed models. The dependent variable was whether the produced form was target or not (1 vs. 0), and whether the produced form was those classified as correct or not (1 vs. 0). Language (5 levels), the argument type of the wh-phrase (2 levels; subject vs. object), the type of wh-phrase (2 levels; who vs. which), and the interaction between the argument type and the type of wh-phrase were the fixed effects, and participant and item were the random effect.

  • Sum coding for who vs. which (c_wh), and subject vs. object (c_arg)

  • Stats to see the effect of the argument type of wh-phrase (subjet vs. object) and type of wh-phrase (who vs. which) on the production of target form (Table 3)

  • We take out Malayalam from the analysis for the production of the target form, because almost all the production in Malayalam were in cleft.

target.df <- all.select %>%
        filter(lang != "malayalam") %>%
        filter(wh.type != "whatQ")

target.df$lang <- factor(target.df$lang, levels = c("german", "hungarian", "mandarin", "yoruba"))

target.df <- target.df %>%
  select(c("lang", "wh.type", "argument.type", "item.order", "item.no", "participant", "target", "correct"))

target.df$lang <- as.factor(target.df$lang)
contrasts(target.df$lang) <- contr.sum(4)

## sum code who as +1/2, which as -1/2
target.df <- target.df %>%
        mutate(c_wh = case_when(wh.type == "whoQ" ~ 1/2, 
                                TRUE ~ -1/2))

## sum code subj as +1/2, obj as -1/2
target.df <- target.df %>%
        mutate(c_arg =  case_when(argument.type == "subject" ~ 1/2,
                                  TRUE ~ -1/2))

## centering the order of items
target.df <- target.df %>%
        mutate(c_item.order =  item.order - mean(1:30))

m1 <- glm(target ~ lang/(c_wh * c_arg), 
            family = binomial(), 
            target.df)
summary(m1)

## maximal model that converged

m2 <- glmer(target ~ lang/(c_wh * c_arg) + c_item.order  + (1 | item.no),
          family = binomial(), 
          target.df)
summary(m2)
## 
## Correlation matrix not shown by default, as p = 17 > 12.
## Use print(x, correlation=TRUE)  or
##     vcov(x)        if you need it
#alpha
0.05/12

Stats to see the effect of the argument type of wh-phrase (subjet vs. object) and type of wh-phrase (who vs. which) on the production of adult-like structures

adultlike.df <- all.select %>%
        filter(wh.type != "whatQ")

adultlike.df$lang <- factor(adultlike.df$lang, levels = c("german", "hungarian", "malayalam", "mandarin", "yoruba"))

adultlike.df <- adultlike.df %>%
  select(c("lang", "wh.type", "argument.type", "item.order", "item.no", "participant", "target", "correct"))

adultlike.df$lang <- as.factor(adultlike.df$lang)
contrasts(adultlike.df$lang) <- contr.sum(5)

## sum code who as +1/2, which as -1/2
adultlike.df <- adultlike.df %>%
        mutate(c_wh = case_when(wh.type == "whoQ" ~ 1/2, 
                                TRUE ~ -1/2))

## sum code subj as +1/2, obj as -1/2
adultlike.df <- adultlike.df %>%
        mutate(c_arg =  case_when(argument.type == "subject" ~ 1/2,
                                  TRUE ~ -1/2))
## center the item order
adultlike.df <- adultlike.df %>%
        mutate(c_item.order =  item.order - mean(1:30))


m1a <- glm(correct ~ lang/(c_wh * c_arg), 
            family = binomial(), 
            adultlike.df)
summary(m1a)

## maximal model that converged

m2a <- glmer(correct ~ lang/(c_wh * c_arg)  + c_item.order + (1 | item.no),
          family = binomial(), 
          adultlike.df)
summary(m2a)
## 
## Correlation matrix not shown by default, as p = 21 > 12.
## Use print(x, correlation=TRUE)  or
##     vcov(x)        if you need it
# This filters the data to only one language BEFORE calculating means
em_target <- emmeans(m2a, ~ c_wh * c_arg, at = list(lang = "mandarin"))
## NOTE: Results may be misleading due to involvement in interactions
# View the means
print(em_target)

# 1. Input emmeans data
results <- data.frame(
  c_wh = factor(c("which", "who", "which", "who")),
  c_arg = factor(c("object", "object", "subject", "subject")),
  emmean = c(1.0396538, 0.6572234, 1.2417939, 2.7132424),
  LCL = c(0.5433352, 0.1897139, 0.7263468, 1.9312020),
  UCL = c(1.535972, 1.124733, 1.757241, 3.495283)
)

results <- results %>%
  mutate(
    c_wh = factor(c_wh, levels = c("who", "which")),
    c_arg = factor(c_arg, levels = c("subject", "object"))
  )

# 3. Figure 7 (the order will now follow the factor levels)
ggplot(results, aes(x = c_arg, y = emmean, color = c_wh, group = c_wh)) +
  geom_line(size = 1.2) +
  geom_point(size = 3) +
  geom_errorbar(aes(ymin = LCL, ymax = UCL), width = 0.1, size = 1) +
  theme_classic() +
  labs(
    title = "Interaction Plot for Mandarin: wh-phrase * argument",
    x = "argument type",
    y = "Estimated Marginal Mean",
    color = "wh-phrase"
  ) +
theme(
    plot.title = element_text(size = 18), # Big bold title
    axis.title = element_text(size = 16),               # X and Y axis titles
    axis.text = element_text(size = 12),                # The numbers/labels on axes
    legend.title = element_text(size = 14),             # Legend title size
    legend.text = element_text(size = 12),               # Legend item size
 )
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once per session.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

# Perform pairwise comparisons for just this language
contrast(em_target, method = "pairwise")



#alpha
0.05/15

Table 7: Use of passive

# Table 7
coded.data%>%
        group_by(lang) %>%
        filter(correct == 1) %>%
        summarise(n(), sum(s.pass), sum(l.pass))

Table 8: Use of null-pro, overt pronoun, and bare which

coded.data %>%
        filter(!is.na(wh.type)) %>%
        filter(correct == 1 & wh.type != "whatQ") %>%
        group_by(lang, argument.type) %>%
        summarise(n(), null.p = sum(covert.pro), overt.p = sum(overt.pro), sum(pronom), bare.wh = sum(drop.after.which))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang and argument.type.
## ℹ Output is grouped by lang.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type))` for per-operation grouping
##   (`?dplyr::dplyr_by`) instead.

Table 9

coded.data %>%
        filter(correct== 1 & wh.type != "whatQ") %>%
        group_by(lang, argument.type) %>%
        summarise(n(), cl = sum(cleft), top = sum(topic), dis = sum(dislocation))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang and argument.type.
## ℹ Output is grouped by lang.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type))` for per-operation grouping
##   (`?dplyr::dplyr_by`) instead.

Errors

all.select %>%
        filter(wh.type != "whatQ") %>%
        filter(correct == 0) %>%
        group_by(grammatical, argument.type) %>%
        summarise(n())
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by grammatical and argument.type.
## ℹ Output is grouped by grammatical.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(grammatical, argument.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.
yy <- coded.data %>%
        filter(correct == 0 & grammatical == 1) %>%
        filter(wh.type != "whatQ") %>%
        group_by(lang, argument.type) %>%
        summarise(n(), inv = sum(role.inversion), what.who=sum(what.for.who), who.which =sum(who.for.which), what.which=sum(what.for.which), who.what = sum(who.for.what),  which.who=sum(which.for.who), tense = sum(tense.aspect))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang and argument.type.
## ℹ Output is grouped by lang.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type))` for per-operation grouping
##   (`?dplyr::dplyr_by`) instead.
coded.data %>%
        filter(correct == 0 & grammatical == 1) %>%
        filter(wh.type != "whatQ") %>%
        #group_by(lang, argument.type) %>%
        summarise(n(), inv = sum(role.inversion), what.who=sum(what.for.who), who.which =sum(who.for.which), what.which=sum(what.for.which), who.what = sum(who.for.what),  which.who=sum(which.for.who), tense = sum(tense.aspect))
ug <- coded.data %>%
        filter(wh.type != "whatQ") %>%
        filter(grammatical == 0) %>%
        group_by(lang, argument.type) %>%
        summarise(n(), w.case = sum(case.error), fragment = sum(frag), sum(num.error), sum(verb.num), sum(covert.pro), sum(resumptive))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang and argument.type.
## ℹ Output is grouped by lang.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type))` for per-operation grouping
##   (`?dplyr::dplyr_by`) instead.
ug.other <- coded.data %>%
        filter(wh.type != "whatQ") %>%
        filter(grammatical == 0) %>%
        group_by(lang, argument.type) %>%
        summarise(sum(other.error), sum(other.grammar), sum(no.res))
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang and argument.type.
## ℹ Output is grouped by lang.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, argument.type))` for per-operation grouping
##   (`?dplyr::dplyr_by`) instead.

some items had two case marked phrases (both wh and DP). We check whether this affected the production of target/alternate structure in German.

second.case <- c("O2", "O3", "S2")
temp1 <- all.select %>%
        mutate(additional.case = case_when(
                item.no %in% second.case ~1, 
                TRUE ~ 0
        ))
temp1 <- temp1 %>%
        filter(lang == "german") %>%
        filter(wh.type != "whatQ") 

temp1 %>%
        group_by(wh.type, argument.type, additional.case) %>%
        summarise(n = n(), total = sum(target), pr = total/n)
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by wh.type, argument.type, and
##   additional.case.
## ℹ Output is grouped by wh.type and argument.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(wh.type, argument.type, additional.case))` for
##   per-operation grouping (`?dplyr::dplyr_by`) instead.
temp1$additional.case <- as.factor(temp1$additional.case)

model.temp <- glmer(target ~ additional.case + (1 | participant) + (1 | item.no),
          family = binomial(), data = temp1)

summary(model.temp)

model.temp <- glmer(target ~ additional.case*argument.type + (1 | participant) + (1 | item.no),
          family = binomial(), data = temp1)

summary(model.temp)

resumptive expressions

As written in footnote 26, we searched for resumptions, which were found in previous production experiments on relative clauses and long distance wh-questions, but not in short-distance matrix wh-questions.

all.select %>%
        filter(resumptive == 1) %>%
        group_by(lang, wh.type, argument.type) %>%
        summarise(n())
## `summarise()` has regrouped the output.
## ℹ Summaries were computed grouped by lang, wh.type, and argument.type.
## ℹ Output is grouped by lang and wh.type.
## ℹ Use `summarise(.groups = "drop_last")` to silence this message.
## ℹ Use `summarise(.by = c(lang, wh.type, argument.type))` for per-operation
##   grouping (`?dplyr::dplyr_by`) instead.
sessionInfo()