#> 
#> ************
#> Welcome to scienceverse For support and examples visit:
#> http://scienceverse.github.io/
#> - Get and set global package options with: scienceverse_options()
#> ************

One goal of scienceverse is to automate the evaluation of predictions. A researcher specifies the prediction in the preregistration, collects the data, and the scienceverse R package (or other platforms that handle scienceverse-formatted files) can then use the preregistration file and the data to automatically evaluate whether the predictions were confirmed or not.

The demo below follows the example from:

Lakens, D., & DeBruine, L. M. (2020, January 27). Improving Transparency, Falsifiability, and Rigour by Making Hypothesis Tests Machine Readable. https://doi.org/10.31234/osf.io/5xcda

Set up the study

Set up the study with a name and any additional info you want to add.

study <- study(name = "Kinship and Prosocial Behaviour",
               abstract = "A reanalysis of data from DeBruine (2002) Facial Resemblance Enhances Trust, PRSLB.")

Authors

Add each author in the following format. Use the function credit_roles() to see a list of the roles and their descriptions. Use credit_roles("name") or credit_roles("abbr") to just see their names or abbreviations. You can also add any further info, like an orcid or email address.

study <- add_author(study, 
                    orcid = "0000-0002-7523-5539",
                    surname = "DeBruine",
                    given = "Lisa M.",
                    roles = c("con", "dat", "sof", "dra", "edi"),
                    email = "lisa.debruine@glasgow.ac.uk") %>%
         add_author(orcid = "0000-0002-0247-239X",
                    surname = "Lakens",
                    given = "Daniël",
                    roles = c("con", "ana", "dra", "edi"))

Hypotheses

Now add a hypothesis with a verbal description. You can add more than one hypothesis, but this demo study only has one.

study <- add_hypothesis(study, id = "self_pref",
                        description = "Cues of kinship will increase prosocial behaviour. Cues of kinship will be manipulated by morphed facial self-resemblance. Prosocial behaviour will be measured by responses in the trust game. The prediction is that the number of trusting AND/OR reciprocating moves will be greater to self morphs than to other morphs.")

Analyses

Add all relevant analyses for testing this hypothesis in the order that they should be run. Do any data prep first. Each analysis needs an id for reference in the criteria later. The code can be R code (wrap it in {} if you need more than one line) or the file path for a .R file. You can also add other information about your analysis, such as the software it’s running on.

study <- add_analysis(study, id = "trust",
                      code = t.test(kin$trust_self, 
                                    kin$trust_other, 
                                    paired = TRUE, 
                                    conf.level = 0.975), 
                      software = R.version.string) %>%
         add_analysis(id = "recip",
                      code = t.test(kin$recip_self,
                                    kin$recip_other,
                                    paired = TRUE,
                                    conf.level = 0.975), 
                      software = R.version.string)

If your analysis was run using other software or you only have summary statistics available, you can add a list of arbitrary named values like this (setting unknown values to NA for preregistration):

study <- add_analysis(study, id = "tr_self",
                      code = list(
                        t = -2.50,
                        df = 23,
                        p = 0.0198,
                        ci = c(-0.9787, -0.0213),
                        estimate = -0.5,
                        stderr = 0.2,
                        description = "two-tailed paired t-test of trust_self vs recip_self"
                      ), 
                      software = "SPSS")

Criteria

Next, add the criteria you will need to check to corroborate or falsify each hypothesis. Each criterion needs a unique id so you can reference it next in the evaluation. Then, optionally specify the hypothesis_id and analysis_id where you’ll look for the result. If you omit these it will default to the last one added. For example, the analysis trust returns a list from the function t.test, which includes a value for conf.int. To see if the first number in this vector is larger than 0, set result to “conf.int[1]”, operator to “>” , and comparator to \(0\). The options for operator are “>”, “<”, “=”, and “!=”.

study <- study %>%
  add_criterion(id = "t_lo",
                result = "conf.int[1]",
                operator = ">",
                comparator = 0.0,
                analysis_id = "trust",
                hypothesis_id = "self_pref") %>%
  add_criterion("t_hi", "conf.int[2]", ">", 0.2, "trust") %>%
  add_criterion("r_lo", "conf.int[1]", ">", 0.0, "recip") %>%
  add_criterion("r_hi", "conf.int[2]", ">", 0.2, "recip")

Evaluation

Add evaluation criteria for corroboration and falsification. The logical evaluation should reference the criterion ids above and can consist of those ids and the symbols (, ), &, and |. You can optionally include a verbal description of the criterion to clarify the logical evaluation.

study <- add_eval(study, "corroboration",
                  evaluation = "(t_lo & t_hi) | (r_lo & r_hi)",
                  description = "The hypothesis is corroborated if the 97.5% CI lower bound is greater than 0 and the 97.5% CI upper bound is greater than 0.2 (the SESOI) for either the trust or reciprocation moves.")

study <- add_eval(study, "falsification",
                  evaluation = "!t_hi & !r_hi",
                  description = "The hypothesis is falsified if the 97.5% CI upper bound is smaller than 0.2 (the SESOI) for both trust and reciprocation.")

Saving

At this point, you can save your study to a machine-readable JSON-formatted file.

study_save(study, "prereg.json", format = "json")
#> Saving to /Users/lisad/rproj/scienceverse/scienceverse/vignettes/prereg.json

You can also export a human-readable pre-registration using the built-in “prereg” template.

study_save(study, "prereg.html", format = "prereg")
#> Saving to /Users/lisad/rproj/scienceverse/scienceverse/vignettes/prereg.html

Data

The id you give the data can be used in the analysis code to refer to this dataset. The data argument can be a data frame or a file path to a data file or a PsychDS-formatted codebook. You can optionally add column parameters such as descriptions with the argument vardesc and other dataset parameters as additional arguments.

kin_data <- data.frame(
  trust_self  = c(1,2,2,1,1,1,1,1,2,0,2,0,1,2,2,3,2,2,1,1,2,0,0,1),
  trust_other = c(1,2,2,0,1,0,0,0,1,0,1,0,1,1,1,0,1,2,2,0,0,0,2,1),
  recip_self  = c(0,1,3,2,1,1,1,3,3,2,3,1,1,2,3,3,3,1,1,1,3,0,3,1),
  recip_other = c(1,1,2,2,3,2,1,3,3,1,3,0,1,3,3,3,3,0,3,0,1,0,3,2)
)

desc <- list(
  description = list(
    trust_self  = "Number of trusting moves towards self-morphs",
    trust_other = "Number of trusting moves towards self-morphs",
    recip_self  = "Number of reciprocating moves towards other-morphs",
    recip_other = "Number of reciprocating moves towards other-morphs"
  ),
  dataType = rep("int", 4) # all variables are integer types
)

study <- add_data(study, id = "kin", 
                  data = kin_data, 
                  vardesc = desc, 
                  url = "https://osf.io/ewfhs/")
#> Registered S3 method overwritten by 'faux':
#>   method            from        
#>   print.nested_list scienceverse

Run Analyses

When you run study_analyse, the data are loaded as their id names and the analyses are run in order. For example, the data from the section above will be available to your analyses as a dataframe called kin. The analysis is run in a separate environment, so you won’t see any new objects in the global environment. Therefore, changes you make to, e.g., a dataframe called kin in your global environment won’t affect the analysis. The evaluation of each criterion and hypothesis is printed as a message.

study <- study_analyse(study)
#> Hypothesis self_pref: Cues of kinship will increase prosocial behaviour. Cues of kinship will be manipulated by morphed facial self-resemblance. Prosocial behaviour will be measured by responses in the trust game. The prediction is that the number of trusting AND/OR reciprocating moves will be greater to self morphs than to other morphs.
#> 
#> Criterion t_lo:
#> * conf.int[1] > 0 is TRUE
#> * conf.int[1] = 0.021
#> 
#> Criterion t_hi:
#> * conf.int[2] > 0.2 is TRUE
#> * conf.int[2] = 0.979
#> 
#> Criterion r_lo:
#> * conf.int[1] > 0 is FALSE
#> * conf.int[1] = -0.509
#> 
#> Criterion r_hi:
#> * conf.int[2] > 0.2 is TRUE
#> * conf.int[2] = 0.426
#> 
#> Conclusion: corroborate
#> * Corroborate ((t_lo & t_hi) | (r_lo & r_hi)): TRUE
#> * Falsify (!t_hi & !r_hi): FALSE

Save and reload

At this point, you can save the post-registration version of your study to a JSON-formatted file and also export a human-readable post-registration report.

study_save(study, "postreg.json", "json")
#> Saving to /Users/lisad/rproj/scienceverse/scienceverse/vignettes/postreg.json
study_save(study, "postreg.html", "postreg")
#> Saving to /Users/lisad/rproj/scienceverse/scienceverse/vignettes/postreg.html

You can reload and edit your study by loading the .json file with the study() function.

study2 <- study("postreg.json")

study2 # displays a summary
#> Kinship and Prosocial Behaviour
#> -------------------------------
#> 
#> * Hypotheses: self_pref
#> * Data: kin
#> * Analyses: trust, recip
#> 
#> Hypothesis self_pref: Cues of kinship will increase prosocial behaviour. Cues of kinship will be manipulated by morphed facial self-resemblance. Prosocial behaviour will be measured by responses in the trust game. The prediction is that the number of trusting AND/OR reciprocating moves will be greater to self morphs than to other morphs.
#> 
#> Criterion t_lo:
#> * conf.int[1] > 0 is TRUE
#> * conf.int[1] = 0.021
#> 
#> Criterion t_hi:
#> * conf.int[2] > 0.2 is TRUE
#> * conf.int[2] = 0.979
#> 
#> Criterion r_lo:
#> * conf.int[1] > 0 is FALSE
#> * conf.int[1] = -0.509
#> 
#> Criterion r_hi:
#> * conf.int[2] > 0.2 is TRUE
#> * conf.int[2] = 0.426
#> 
#> Conclusion: corroborate
#> * Corroborate ((t_lo & t_hi) | (r_lo & r_hi)): TRUE
#> * Falsify (!t_hi & !r_hi): FALSE