{"action":"created","comment":{"url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/comments/39921533","id":39921533,"diff_hunk":"@@ -1,698 +1,695 @@\n-\n-TTestIndependentSamples <- function(dataset=NULL, options, perform=\"run\", callback=function(...) 0, ...) {\n-\n-\tdependents <- unlist(options$variables)\n-\t\n-\tgrouping   <- options$groupingVariable\n-\tif (grouping == \"\")\n-\t\tgrouping <- NULL\n-\n-\tif (is.null(dataset))\n-\t{\n-\t\tif (perform == \"run\") {\n-\t\t\n-\t\t\tif (options$missingValues == \"excludeListwise\") {\n-\t\t\n-\t\t\t\tdataset <- .readDataSetToEnd(columns.as.numeric=dependents, columns.as.factor=grouping, exclude.na.listwise=dependents)\n-\t\t\t\n-\t\t\t} else {\n-\t\t\n-\t\t\t\tdataset <- .readDataSetToEnd(columns.as.numeric=dependents, columns.as.factor=grouping)\n-\t\t\t}\n-\t\t\n-\n-\t\t} else {\n-\t\t\n-\t\t\tdataset <- .readDataSetHeader(columns.as.numeric=dependents, columns.as.factor=grouping)\n-\t\t}\n-\t}\n-\n-\tresults <- list()\n-\t\n-\n-\t#### META\n-\t\n-\tmeta <- list()\n-\t\n-\tmeta[[1]] <- list(name=\"title\", type=\"title\")\n-\tmeta[[2]] <- list(name=\"ttest\", type=\"table\")\n-\tmeta[[3]] <- list(name=\"equalityOfVariancesTests\", type=\"table\")\n-\tmeta[[4]] <- list(name=\"descriptives\", type=\"table\")\n-\tmeta[[5]] <- list(name=\"normalityTests\", type=\"table\")\n-\tmeta[[6]] <- list(name=\"headerDescriptivesPlots\", type=\"h1\")\n-\tmeta[[7]] <- list(name=\"descriptivesPlots\", type=\"images\")\n-\t\n-\tresults[[\".meta\"]] <- meta\n-\tresults[[\"title\"]] <- \"T-Test\"\n-\t\n-\tresults[[\"ttest\"]] <- .ttestIndependentSamplesTTest(dataset, options, perform)\n-\tresults[[\"descriptives\"]] <- .ttestIndependentSamplesDescriptives(dataset, options, perform)\n-\tresults[[\"equalityOfVariancesTests\"]] <- .ttestIndependentSamplesInequalityOfVariances(dataset, options, perform)\n-\tresults[[\"normalityTests\"]] <- .ttestNormalityTests(dataset, options, perform)\n-\t\n-\tif (options$descriptivesPlots) {\n-\t\t\n-\t\tif (length(options$variables) > 1) {\n-\t\t\tresults[[\"headerDescriptivesPlots\"]] <-  \"Descriptives Plots\"\n-\t\t} else {\n-\t\t\tresults[[\"headerDescriptivesPlots\"]] <-  \"Descriptives Plot\"\n-\t\t}\n-\t\t\n-\t\tresults[[\"descriptivesPlots\"]] <- .independentSamplesTTestDescriptivesPlot(dataset, options, perform)\n-\t}\n-\n-\tresults\n+TTestIndependentSamples <- function(dataset = NULL, options, perform = \"run\",\n+                                    callback = function(...) 0, ...) {\n+    \n+    ## call the common initialization function\n+    init <- .initialize_ttest(dataset, options, perform)\n+    \n+    results <- init[[\"results\"]]\n+    dataset <- init[[\"dataset\"]]\n+    \n+    ## this is specific for the independent t-test\n+    results[[\".meta\"]][[7]] <- list(name = \"equalityOfVariancesTests\", type = \"table\")\n+    \n+    ## call the specific independent T-Test functions\n+    results[[\"ttest\"]] <- .ttestIndependentSamplesTTest(dataset, options, perform)\n+    results[[\"descriptives\"]] <- .ttestIndependentSamplesDescriptives(dataset, options, perform)\n+    results[[\"equalityOfVariancesTests\"]] <- .ttestIndependentSamplesInequalityOfVariances(dataset, options, perform)\n+    results[[\"normalityTests\"]] <- .ttestIndependentSamplesNormalityTest(dataset, options, perform)\n+    \n+    ## if the user wants descriptive plots, s/he shall get them!\n+    if (options$descriptivesPlots) {\n+        results[[\"descriptivesPlots\"]] <- .independentSamplesTTestDescriptivesPlot(dataset, options, perform)\n+    }\n+    \n+    ## return the results object\n+    results\n }\n \n-.ttestNormalityTests <- function(dataset, options, perform) {\n-\n-\tif (options$normalityTests == FALSE)\n-\t\treturn(NULL)\n-\t\t\n-    normalityTests <- list()\n-\n-    normalityTests[[\"title\"]] <- \"Test of Normality (Shapiro-Wilk)\"\n \n-    fields <- list(\n-        list(name=\"dep\",  type=\"string\", title=\"\", combine=TRUE),\n-        list(name=\"lev\",  type=\"string\", title=\"\"),\n-        list(name=\"W\", title=\"W\", type=\"number\",   format=\"sf:4;dp:3\"),\n-        list(name=\"p\", title=\"p\", type=\"number\", format=\"dp:3;p:.001\"))\n-\n-    normalityTests[[\"schema\"]] <- list(fields=fields)\n+.ttestIndependentSamplesTTest <- function(dataset, options, perform) {\n     \n-    footnotes <- .newFootnotes()\n-    .addFootnote(footnotes, symbol=\"<em>Note.</em>\", text=\"Significant results indicate a deviation from normality\")\n+    ttest <- list()\n+    wants_effect <- options$effectSize\n+    wants_difference <- options$meanDifference\n+    wants_confidence <- options$confidenceInterval\n     \n-    normalityTests.results <- list()\n+    ## can make any combination of the following tests:\n+    wants_welchs <- options$welchs\n+    wants_students <- options$students\n+    wants_wilcox <- options$mannWhitneyU\n+\n+    ## setup table for the independent samples t-test; add column test at the\n+    ## beginning, and remove it later should the user only specify one test\n+    fields <- list(list(name = \"v\", title = \"\", type = \"string\", combine = TRUE),\n+                   list(name = \"test\", type = \"string\", title = \"Test\"),\n+                   list(name = \"df\", type = \"number\", format = \"sf:4;dp:3\"),\n+                   list(name = \"p\", type = \"number\", format = \"dp:3;p:.001\"))\n+\n+\n+    ## if none is specified, give her a Student's t-test (TODO: Welch's is better as default?)\n+    if (!any(wants_welchs, wants_students, wants_wilcox)) {\n+        wants_students <- TRUE\n+    }\n+    \n+    all_tests <- c(wants_students, wants_welchs, wants_wilcox)\n+    only_test <- sum(all_tests) == 1\n+    \n+    ## get the right title of the table\n+    if (wants_wilcox && only_test) {\n+        title <- \"Mann-Whitney U Test\"\n+        \n+        testStat <- \"W\"\n+        ## additionally, Wilcoxon's test doesn't have degrees of freedoms\n+        fields <- fields[-3]\n+    } else if (wants_welchs && only_test) {\n+        title <- \"Welch's T-Test\"\n+        testStat <- \"t\"\n+    } else if (wants_students && only_test) {\n+        title <- \"Student's T-Test\"\n+        testStat <- \"t\"\n+    } else {\n+        title <- \"Independent Sample T-Test\"\n+        testStat <- \"statistic\"\n+    }\n+    \n+    ttest[\"title\"] <- title\n+    \n+    ## if only doing Student's / Welch's, the table should have \"t\" as column name\n+    ## for the test statistic; when doing only Wilcoxon's, the name should be \"W\";\n+    ## when doing both, it should be \"statistic\"\n+    fields <- append(fields, list(list(name = testStat, type = \"number\",\n+                                       format = \"sf:4;dp:3\")), 2)\n+    \n+    ## add mean difference and standard error difference\n+    if (wants_difference) {\n+        fields[[length(fields) + 1]] <- list(name = \"md\", title = \"Mean Difference\",\n+                                             type = \"number\", format = \"sf:4;dp:3\")\n+        fields[[length(fields) + 1]] <- list(name = \"sed\", title = \"SE Difference\",\n+                                             type = \"number\", format = \"sf:4;dp:3\")\n+    }\n+    \n+    ## add Cohen's d\n+    if (wants_effect) {\n+        fields[[length(fields) + 1]] <- list(name = \"d\", title = \"Cohen's d\",\n+                                             type = \"number\", format = \"sf:4;dp:3\")\n+    }\n     \n-\tvariables <- options$variables\n-\tif (length(variables) == 0)\n-\t\tvariables = \".\"\n+    ## I hope they know what they are doing! :)\n+    if (wants_confidence) {\n+        interval <- 100 * options$confidenceIntervalInterval\n+        title <- paste0(interval, \"% Confidence Interval\")\n+        \n+        fields[[length(fields) + 1]] <- list(name = \"lowerCI\", type = \"number\",\n+                                             format = \"sf:4;dp:3\", title = \"Lower\",\n+                                             overTitle = title)\n+        fields[[length(fields) + 1]] <- list(name = \"upperCI\", type = \"number\",\n+                                             format = \"sf:4;dp:3\", title = \"Upper\",\n+                                             overTitle = title)\n+    }\n+    \n+    ## add all the fields that we may or may not have added\n+    ## in the initialization phase, remove the Test column\n+    ttest[[\"schema\"]] <- list(fields = fields[-2])\n+    \n+    ## check if we are ready to perform!\n+    ready <- (perform == \"run\" && length(options$variables) != 0\n+              && options$groupingVariable != \"\")\n+    \n+    ttest.rows <- list()\n+    footnotes <- .newFootnotes()\n+    variables <- options$variables\n+    if (length(variables) == 0) variables <- \".\"\n \n+    ## add a row for each variable\n     for (variable in variables) {\n-    \n-    \tcount <- 0\n+        ttest.rows[[length(ttest.rows) + 1]] <- list(v = variable)\n+    }\n+\n+    if (ready) {\n+        levels <- base::levels(dataset[[ .v(options$groupingVariable) ]])\n         \n-        factor <- options$groupingVariable\n-        levels <- levels(dataset[[ .v(factor) ]])\n-                        \n-        if (length(levels) == 0)\n-        \tlevels = c(\".\", \".\")\n+        ## if there aren't exactly two levels, abort the mission\n+        if (length(levels) != 2) {\n+            error <- \"The Grouping Variable must have 2 levels\"\n+            ttest[[\"error\"]] <- list(errorType = \"badData\", errorMessage = error)\n+            ttest[[\"data\"]] <- ttest.rows\n+            return(ttest)\n+        }\n         \n-        for(level in levels) {\n-        \t\n-        \tcount <- count + 1\n-                    \n-            if (perform == \"run\" && length(options$variables) > 0 && !is.null(levels(dataset[[ .v(factor) ]]))) {\n-                \n-                data <- na.omit(dataset[[.v(variable)]][dataset[[.v(factor)]] == level])\n-                \n-                row.footnotes <- NULL\n-                error <- FALSE\n-                \n-                if(length(data) < 3) {\n+        ## does the user have a direction in mind?\n+        if (options$hypothesis == \"groupOneGreater\") {\n+            \n+            direction <- \"greater\"\n+            message <- paste0(\"All tests, hypothesis is group <em>\", levels[1],\n+                              \"</em> greater than group <em>\", levels[2], \"</em>\")\n+            .addFootnote(footnotes, symbol = \"<em>Note.</em>\", text = message)\n+            \n+        } else if (options$hypothesis == \"groupTwoGreater\") {\n+            \n+            direction <- \"less\"\n+            message <- paste0(\"All tests, hypothesis is group <em>\", levels[1],\n+                              \"</em> less than group <em>\", levels[2], \"</em>\")\n+            .addFootnote(footnotes, symbol = \"<em>Note.</em>\", text = message)\n+            \n+        } else {\n+            direction <- \"two.sided\"\n+        }\n+        \n+        \n+        rowNo <- 1\n+        which_tests <- list(\"1\" = wants_students, \"2\" = wants_welchs, \"3\" = wants_wilcox)\n+        groupingData <- dataset[[ .v(options$groupingVariable) ]]\n+        \n+        ## for each variable specified, run each test that the user wants\n+        for (variable in options$variables) {\n+            \n+            variableData <- dataset[[ .v(variable) ]]\n+\n+            ## test is a number, indicating which tests should be run\n+            for (test in seq_len(length(which_tests))) {\n                 \n-                    foot.index <- .addFootnote(footnotes, \"Too few datapoints (N < 3) to compute statistic reliably\")\n-\t\t\t\t\trow.footnotes <- list(W=list(foot.index), p=list(foot.index))\n-\t\t\t\t\terror <- TRUE\n-\t\t\t\t\t\n-                } else if(length(data) > 5000) {\n+                current_test <- which_tests[[test]]\n                 \n-                    foot.index <- .addFootnote(footnotes, \"Too many datapoints (N > 5000) to compute statistic reliably\")\n-\t\t\t\t\trow.footnotes <- list(W=list(foot.index), p=list(foot.index))\n-\t\t\t\t\terror <- TRUE\n-\t\t\t\t\t\n+                ## don't run a test the user doesn't want\n+                if (!current_test) {\n+                    next\n                 }\n-                \n-                if (!error) {\n-                \n-                    r <- stats::shapiro.test(data)\n-                \n-                    W <- .clean(as.numeric(r$statistic))\n-                    p <- .clean(r$p.value)\n-                \n-                    if(level == levels[1]) {\n-                        newGroup <- TRUE   \n-                    } else {\t\t\t\t\n-                        newGroup <- FALSE\n+\n+                ## try to run the test, catching eventual errors\n+                row <- try(silent = FALSE, expr = {\n+\n+                    row.footnotes <- NULL\n+                    ci <- options$confidenceIntervalInterval # what a mouthful!\n+                    f <- as.formula(paste(.v(variable), \"~\",\n+                                          .v(options$groupingVariable)))\n+\n+                    if (test == 3) {\n+                        what_test <- \"Mann-Whitney\"\n+                        r <- stats::wilcox.test(f, data = dataset,\n+                                                alternative = direction,\n+                                                conf.int = TRUE, conf.level = ci, paired = FALSE)\n+                        df <- \"\"\n+                        m <- as.numeric(r$estimate)\n+\n+                    } else {\n+                        what_test <- ifelse(test == 2, \"Welch's\", \"Student's\")\n+                        r <- stats::t.test(f, data = dataset, alternative = direction,\n+                                           var.equal = test != 2, conf.level = ci, paired = FALSE)\n+\n+                        df <- as.numeric(r$parameter)\n+                        m <- as.numeric(r$estimate[1]) - as.numeric(r$estimate[2])\n+                    }\n+\n+                    ## if the user doesn't want a Welch's t-test,\n+                    ## give a footnote indicating if the equality of variance\n+                    ## assumption is met; seems like in this setting there is no\n+                    ## sampling plan, thus the p-value is not defined. haha!\n+                    if (!wants_welchs && wants_students) {\n+                        levene <- car::leveneTest(variableData, groupingData, \"mean\")\n+                  \n+                        ## arbitrary cut-offs are arbitrary\n+                        if (!is.na(levene[1, 3]) && levene[1, 3] < 0.05) {\n+                            error <- paste0(\"Levene's test is significant (p < .05), \",\n+                                            \"suggesting a violation of the equal \",\n+                                            \"variance assumption\")\n+                            foot.index <- .addFootnote(footnotes, error)\n+                            row.footnotes <- list(p = list(foot.index))\n+                        }\n                     }\n                 \n-                    result <- list(\"dep\"=variable, \"lev\"=level, \"W\" = W, \"p\" = p, \".isNewGroup\" = newGroup)\n+                    ## same for all t-tests\n+                    p <- as.numeric(r$p.value)\n+                    stat <- as.numeric(r$statistic)\n+                    y <- dataset[[ .v(variable) ]]\n+                    groups <- dataset[[ .v(options$groupingVariable) ]]\n                 \n-                } else {\n+                    sds <- tapply(y, groups, sd, na.rm = TRUE)\n+                    ms <- tapply(y, groups, mean, na.rm = TRUE)\n+                    ns <- tapply(y, groups, function(x) length(na.omit(x)))\n+\n+                    num <- sqrt(((ns[1] - 1) * sds[1]^2 + (ns[2] - 1) * sds[2]^2))\n+                    sdPooled <- num / (ns[1] + ns[2] - 2)\n+                    d <- as.numeric((ms[1] - ms[2]) / sdPooled) # Cohen's d\n                 \n-                    if(level == levels[1]) {\n-                        newGroup <- TRUE   \n-                    } else {\t\t\t\t\n-                        newGroup <- FALSE\n-                    }\n+                    sed <- .clean(as.numeric(sqrt(sds[1]^2 / ns[1] + sds[2]^2 / ns[2])))\n+                    ciLow <- .clean(r$conf.int[1])\n+                    ciUp <- .clean(r$conf.int[2])\n                 \n-                    result <- list(\"dep\"=variable, \"lev\"=level, \"W\" = \"NaN\", \"p\" = \"NaN\", \".isNewGroup\" = newGroup, .footnotes=row.footnotes)\n-                                    \n+                    ## this will be the results object\n+                    res <- list(v = variable, test = what_test, df = df, p = p,\n+                                md = m, d = d, lowerCI = ciLow, upperCI = ciUp,\n+                                sed = sed, .footnotes = row.footnotes)\n+                    res[[testStat]] <- stat\n+                    res\n+                 })\n+\n+                ## if there has been an error in computing the test, log it as footnote\n+                if (class(row) == \"try-error\") {\n+                    errorMessage <- .extractErrorMessage(row)\n+                    \n+                    if (errorMessage == \"missing value where TRUE/FALSE needed\" &&\n+                        any(is.finite(variableData) == FALSE)) {\n+                        \n+                        err <- \"t-statistic is undefined - the dependent variable contains infinity\"\n+                      \n+                    } else if (errorMessage == \"grouping factor must have exactly 2 levels\") {\n+                      \n+                        # We know that the grouping factor *does* have two levels,\n+                        # because we've checked this earlier on. This error means\n+                        # that all of one factor has been excluded\n+                        # because of missing values in the dependent\n+                        err <- paste0(\"t-statistic is undefined - the grouping \",\n+                                      \"variable contains less than two levels once \",\n+                                      \"missing values in the dependent are excluded\")\n+                      \n+                    } else if (errorMessage == \"data are essentially constant\") {\n+                      errorMessage <- paste0(\"t-statistic is undefined - one or both \",\n+                                             \"levels of the dependent contains all the \",\n+                                             \"same value (zero variance)\")\n+                      \n+                    } else if (errorMessage == \"not enough observations\") {\n+                      errorMessage <- paste0(\"t-statistic is undefined - one or both levels \",\n+                                            \" of the dependent contain too few observations\")\n+                    }\n+                    \n+                    ## log the error in a footnote\n+                    index <- .addFootnote(footnotes, errorMessage)\n+                    row.footnotes <- list(t = list(index))\n+                    \n+                    row <- list(v = variable, test = \"\", df = \"\", p = \"\",\n+                                md = \"\", lowerCI = \"\", upperCI = \"\",\n+                                sed = \"\", .footnotes = list(t = list(index)))\n+                    row[[testStat]] <- .clean(NaN)\n                 }\n-        \n-            } else {\n-        \n-                if(count == 1) {\n-                    newGroup <- TRUE   \n-                } else {\n-                    newGroup <- FALSE\n+                \n+                ## if the user only wants more than one test\n+                ## update the table so that it shows the \"Test\" and \"statistic\" column\n+                if (sum(all_tests) > 1) {\n+                    ttest[[\"schema\"]] <- list(fields = fields)\n                 }\n-        \n-                result <- list(\"dep\"=variable, \"lev\"=level, \"W\" = \".\", \"p\" = \".\", \".isNewGroup\" = newGroup)\n-        \n+                \n+                ttest.rows[[rowNo]] <- row\n+                rowNo <- rowNo + 1\n             }\n-        \n-            normalityTests.results[[length(normalityTests.results)+1]] <- result\n         }\n+        ttest[[\"footnotes\"]] <- as.list(footnotes)\n     }\n     \n-    normalityTests[[\"data\"]] <- normalityTests.results\n+    ttest[[\"data\"]] <- ttest.rows\n+    ttest\n+}\n+\n+\n+.ttestIndependentSamplesDescriptives <- function(dataset, options, perform,\n+                                                 state = NULL, diff = NULL) {\n+    if (options$descriptives == FALSE) return(NULL)\n     \n-    normalityTests[[\"footnotes\"]] <- as.list(footnotes)\n+    descriptives = list(\"title\" = \"Group Descriptives\")\n+\n+    ## sets up the table for the descriptives\n+    fields <- list(\n+        list(name = \"variable\", title = \"\", type = \"string\", combine = TRUE),\n+        list(name = \"group\", title = \"Group\", type = \"string\"),\n+        list(name = \"N\", title = \"N\", type = \"number\"),\n+        list(name = \"mean\", title = \"Mean\", type = \"number\", format = \"sf:4;dp:3\"),\n+        list(name = \"sd\", title = \"SD\", type = \"number\", format = \"sf:4;dp:3\"),\n+        list(name = \"se\", title = \"SE\", type = \"number\", format = \"sf:4;dp:3\")\n+    )\n     \n-    normalityTests\n-}\n+    descriptives[[\"schema\"]] <- list(fields = fields)\n+    data <- list()\n+\n+\n+    ## function to check if everything is alright with the options\n+    is_allright <- function(variable, options, state = NULL, diff = NULL) {\n \n+        # check if the variable is in the state variables\n+        cond1 <- !is.null(state) && variable %in% state$options$variables\n \n-.ttestIndependentSamplesDescriptives <- function(dataset, options, perform, state=NULL, diff=NULL) {\n-\n-\tif (options$descriptives == FALSE)\n-\t\treturn(NULL)\n-\t\t\n-\tdescriptives <- list()\n-\n-\tdescriptives[[\"title\"]] <- \"Group Descriptives\"\n-\t\n-\tfields <- list(\n-\t\tlist(name=\"variable\", title=\"\", type=\"string\", combine=TRUE),\n-\t\tlist(name=\"group\",    title=\"Group\", type=\"string\"),\n-\t\tlist(name=\"N\",        title=\"N\", type=\"number\"),\n-\t\tlist(name=\"mean\",     title=\"Mean\", type=\"number\", format=\"sf:4;dp:3\"),\n-\t\tlist(name=\"sd\",       title=\"SD\", type=\"number\", format=\"sf:4;dp:3\"),\n-\t\tlist(name=\"se\",       title=\"SE\", type=\"number\", format=\"sf:4;dp:3\"))\n-\n-\tdescriptives[[\"schema\"]] <- list(fields=fields)\n-\t\n-\tdata <- list()\n-\t\n-\tvariables <- options[[\"variables\"]]\n-\tif (length(variables) == 0)\n-\t\tvariables <- \".\"\n-\t\n-\t\n-\tfor (variable in variables) {\n-\t\n-\t\tif (!is.null(state) && variable %in% state$options$variables && !is.null(diff) && ((is.logical(diff) && diff == FALSE) || (is.list(diff) && (diff$descriptives == FALSE &&\n-\t\t\tdiff$groupingVariable == FALSE && diff$missingValues == FALSE)))) {\n-\t\t\n-\t\t\tdescriptivesVariables <- character(length(state$results$descriptives$data))\n+        # check if either diff is true, or it's a list and descriptives,\n+        # and groupingVariable, missingValues are FALSE\n+        cond2 <- (!is.null(diff) && (is.logical(diff) && diff == FALSE) || (is.list(diff)\n+                 && !any(diff$descriptives,diff$groupingVariable, diff$missingValues)))\n+\n+        cond1 && cond2\n+    }\n+    \n+    variables <- options$variables\n+    if (length(variables) == 0) variables <- \".\"\n+    \n+    for (variable in variables) {\n+        \n+        if (is_allright(variable, options, state, diff)) {\n+            \n+            state_dat <- state$results$descriptives$data\n+\t\t\tdescriptivesVariables <- as.character(length(state_dat))\n \t\t\t\n-\t\t\tfor (i in seq_along(state$results$descriptives$data)) \n-\t\t\t\tdescriptivesVariables[i] <- state$results$descriptives$data[[i]]$variable\n+\t\t\tfor (i in seq_along(state_dat))\n+\t\t\t\tdescriptivesVariables[i] <- state_dat[[i]]$variable\n \t\t\t\n \t\t\tindices <- which(descriptivesVariables == variable)\n-\t\t\t\n-\t\t\tdata[[length(data)+1]] <- state$results$descriptives$data[[indices[1]]]\n-\t\t\tdata[[length(data)+1]] <- state$results$descriptives$data[[indices[2]]]\n-\t\t\n-\t\t} else {\n-\t\n-\t\t\tdata[[length(data)+1]] <- list(variable=variable, .isNewGroup=TRUE)\n-\t\t\tdata[[length(data)+1]] <- list(variable=variable)\n-\t\t}\n-\t}\n-\t\n-\tif (!is.null(state) && all(variables %in% state$options$variables) && state$options$descriptives)\n-\t\tdescriptives[[\"status\"]] <- \"complete\"\n-\t\n-\tif (perform == \"run\" && options$groupingVariable != \"\") {\n-\t\n-\t\tlevels <- base::levels(dataset[[ .v(options$groupingVariable) ]])\n-\t\t\n-\t\tif (length(levels) != 2) {\n-\t\t\n-\t\t\tdescriptives[[\"error\"]] <- list(errorType=\"badData\")\n-\t\t\t\n-\t\t} else {\n-\t\t\n-\t\t\trowNo <- 1\n-\t\t\tgroupingData <- dataset[[ .v(options$groupingVariable) ]]\n-\t\t\n-\t\t\tfor (variable in options[[\"variables\"]]) {\n-\t\t\t\n-\t\t\t\tif (!is.null(state) && variable %in% state$options$variables && !is.null(diff) && ((is.logical(diff) && diff == FALSE) || (is.list(diff) && (diff$descriptives == FALSE &&\n-\t\t\t\t\tdiff$groupingVariable == FALSE && diff$missingValues == FALSE)))) {\n-\t\t\t\n-\t\t\t\t\tdescriptivesVariables <- character(length(state$results$descriptives$data))\n-\t\t\t\t\t\n-\t\t\t\t\tfor (i in seq_along(state$results$descriptives$data)) \n-\t\t\t\t\t\tdescriptivesVariables[i] <- state$results$descriptives$data[[i]]$variable\n-\t\t\t\t\t\n-\t\t\t\t\tindices <- which(descriptivesVariables == variable)\n-\t\t\t\t\t\n-\t\t\t\t\tdata[[rowNo]] <- state$results$descriptives$data[[indices[1]]]\n-\t\t\t\t\tdata[[rowNo+1]] <- state$results$descriptives$data[[indices[2]]]\n-\t\t\t\t\t\n-\t\t\t\t\trowNo <- rowNo + 2\n-\t\t\t\n-\t\t\t\t} else {\n-\t\t\t\n-\t\t\t\t\tfor (i in 1:2) {\n-\t\t\t\t\n-\t\t\t\t\t\tlevel <- levels[i]\n-\t\t\t\t\t\tvariableData <- dataset[[ .v(variable) ]]\n-\t\t\t\t\t\n-\t\t\t\t\t\tgroupData <- variableData[groupingData == level]\n-\t\t\t\t\t\tgroupDataOm <- na.omit(groupData)\n-\t\n-\t\t\t\t\t\tif (class(groupDataOm) != \"factor\") {\n-\t\n-\t\t\t\t\t\t\tn <- .clean(length(groupDataOm))\n-\t\t\t\t\t\t\tmean <- .clean(mean(groupDataOm))\n-\t\t\t\t\t\t\tstdDeviation <- .clean(sd(groupDataOm))\n-\t\t\t\t\t\t\tstdErrorMean <- .clean(sd(groupDataOm) / sqrt(length(groupDataOm)))\n-\t\t\t\t\t\t\n-\t\t\t\t\t\t\tresult <- list(variable=variable, group=level, N=n, mean=mean, \"sd\"=stdDeviation,\n-\t\t\t\t\t\t\t\t\"se\"=stdErrorMean)\t\t\t\t\t\t\n-\t\t\t\t\t\t\t\t\n-\t\t\t\t\t\t} else {\n-\t\t\t\t\t\n-\t\t\t\t\t\t\tn <- .clean(length(groupDataOm))\n-\t\t\t\t\t\t\tresult <- list(variable=variable, group=\"\", N=n, mean=\"\", \"sd\"=\"\", \"se\"=\"\")\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tif (i == 1)\n-\t\t\t\t\t\t\tresult[[\".isNewGroup\"]] <- TRUE\n-\t\t\t\t\t\n-\t\t\t\t\t\tdata[[rowNo]] <- result\n-\t\t\t\t\t\trowNo <- rowNo + 1\n-\t\t\t\t\t}\n-\t\t\t\t}\n-\t\t\t}\n-\t\t}\n-\t\t\n-\t\tdescriptives[[\"status\"]] <- \"complete\"\n-\t}\n-\t\n-\tdescriptives[[\"data\"]] <- data\n-\n-\tdescriptives\n-}\n+\t\t\tdata[[length(data) + 1]] <- state_dat[[indices[1]]]\n+\t\t\tdata[[length(data) + 1]] <- state_dat[[indices[2]]]\n+            \n+        } else {\n+            data[[length(data) + 1]] <- list(variable = variable, .isNewGroup = TRUE)\n+            data[[length(data) + 1]] <- list(variable = variable)\n+        }\n+    }\n \n-.ttestIndependentSamplesTTest <- function(dataset, options, perform) {\n+    ## check if we are done with all this crap\n+    done <- (!is.null(state) &&\n+             state$options$descriptives &&\n+             all(variables %in% state$options$variables))\n \n-\tttest <- list()\n-\n-\tttest[[\"title\"]] <- \"Independent Samples T-Test\"\n-\n-\tfields <- list(\n-\t\tlist(name=\"v\", title=\"\", type=\"string\", combine=TRUE))\n-\t\n-\tif (options$equalityOfVariances == \"reportBoth\")\t{\n-\t\n-\t\tfields[[length(fields)+1]] <- list(name=\"variances\", title=\"Variances\", type=\"string\")\n-\t}\n-\t\n-\tfields[[length(fields)+1]] <- list(name=\"t\", type=\"number\", format=\"sf:4;dp:3\")\n-\tfields[[length(fields)+1]] <- list(name=\"df\", type=\"number\", format=\"sf:4;dp:3\")\n-\tfields[[length(fields)+1]] <- list(name=\"p\", type=\"number\", format=\"dp:3;p:.001\")\n-\n-\tif (options$meanDifference) {\n-\t\n-\t\tfields[[length(fields) + 1]] <- list(name=\"md\",  title=\"Mean Difference\", type=\"number\", format=\"sf:4;dp:3\")\n-\t\tfields[[length(fields) + 1]] <- list(name=\"sed\", title=\"SE Difference\", type=\"number\", format=\"sf:4;dp:3\")\t\n-\t}\n-\t\n-\tif(options$effectSize){\n-\t\tfields[[length(fields) + 1]] <- list(name=\"d\", title=\"Cohen's d\", type=\"number\", format=\"sf:4;dp:3\")\n-\t}\n-\t\n-\tif (options$confidenceInterval) {\n-\n-\t\tinterval <- 100 * options$confidenceIntervalInterval\n-\t\ttitle    <- paste(interval, \"% Confidence Interval\", sep=\"\")\n-\t\n-\t\tfields[[length(fields) + 1]] <- list(name=\"lowerCI\", type=\"number\", format=\"sf:4;dp:3\", title=\"Lower\", overTitle=title)\n-\t\tfields[[length(fields) + 1]] <- list(name=\"upperCI\", type=\"number\", format=\"sf:4;dp:3\", title=\"Upper\", overTitle=title)\n-\t\t\n-\t}\n-\t\t\n-\tttest[[\"schema\"]] <- list(fields=fields)\n-\t\n-\tttest.rows <- list()\n-\t\n-\tvariables <- options[[\"variables\"]]\n-\tif (length(variables) == 0)\n-\t\tvariables <- \".\"\n-\t\n-\tif (options$equalityOfVariances == \"reportBoth\") {\n-\n-\t\tfor (variable in variables) {\n-\n-\t\t\tttest.rows[[length(ttest.rows)+1]] <- list(v=variable, variances=\"assumed equal\", .isNewGroup=TRUE)\n-\t\t\tttest.rows[[length(ttest.rows)+1]] <- list(v=variable, variances=\"no assumption\")\n-\t\t}\n-\t\t\n-\t} else {\n-\t\n-\t\tfor (variable in variables) {\n-\n-\t\t\tttest.rows[[length(ttest.rows)+1]] <- list(v=variable)\n-\t\t}\n-\t}\n-\t\n-\t\n-\tfootnotes <- .newFootnotes()\n-\n-\tif (options$equalityOfVariances == \"assumeEqual\")\n-\t\t.addFootnote(footnotes, symbol=\"<em>Note.</em>\", text=\"All tests, variances of groups assumed equal\")\n-\tif (options$equalityOfVariances == \"noAssumption\")\n-\t\t.addFootnote(footnotes, symbol=\"<em>Note.</em>\", text=\"All tests, variances of groups not assumed equal\")\n-\t\n-\tif (perform == \"run\" && length(options$variables) != 0 && options$groupingVariable != \"\") {\n-\n-\t\tlevels <- base::levels(dataset[[ .v(options$groupingVariable) ]])\n-\t\t\n-\t\tif (length(levels) != 2) {\n-\t\t\n-\t\t\tttest[[\"error\"]] <- list(errorType=\"badData\", errorMessage=\"The Grouping Variable must have 2 levels\")\n-\t\t\t\n-\t\t} else {\n-\t\t\n-\t\t\tif (options$hypothesis == \"groupOneGreater\") {\n-\n-\t\t\t\tmessage <- paste(\"All tests, hypothesis is group <em>\", levels[1], \"</em> greater than group <em>\", levels[2], \"</em>\", sep=\"\")\n-\t\t\t\t.addFootnote(footnotes, symbol=\"<em>Note.</em>\", text=message)\n-\t\t\t\t\n-\t\t\t\ttestType <- \"greater\"\n-\t\t\n-\t\t\t} else if (options$hypothesis == \"groupTwoGreater\") {\n-\t\n-\t\t\t\tmessage <- paste(\"All tests, hypothesis is group <em>\", levels[1], \"</em> less than group <em>\", levels[2], \"</em>\", sep=\"\")\n-\t\t\t\t.addFootnote(footnotes, symbol=\"<em>Note.</em>\", text=message)\n-\n-\t\t\t\ttestType <- \"less\"\n-\t\t\t\t\n-\t\t\t} else {\n-\t\t\n-\t\t\t\ttestType <- \"two.sided\"\n-\t\t\t}\n-\t\t\n-\t\t\tif (options$equalityOfVariances == \"assumeEqual\") {\n-\t\t\n-\t\t\t\tassume <- c(TRUE)\n-\t\t\t\tassumption=c(\"assumed equal\", NA)\n-\t\t\t\n-\t\t\t} else if (options$equalityOfVariances == \"noAssumption\") {\n-\t\t\n-\t\t\t\tassume <- c(FALSE)\n-\t\t\t\tassumption=c(\"no assumption\", NA)\n-\t\t\t\n-\t\t\t} else {  # assuming both\n-\t\t\n-\t\t\t\tassume <- c(TRUE, FALSE)\n-\t\t\t\tassumption=c(\"assumed equal\", \"no assumption\")\n-\t\t\t}\n-\t\t\n-\t\t\tgroupingData <- dataset[[ .v(options$groupingVariable) ]]\n-\t\t\trowNo <- 1\n-\t\t\t\n-\t\t\tfor (variable in options[[\"variables\"]]) {\n+    if (done) descriptives[[\"status\"]] <- complete\n+    \n+    groups <- options$groupingVariable\n \n-\t\t\t\tvariableData <- dataset[[ .v(variable) ]]\n-\t\t\t\n-\t\t\t\tfor (i in .indices(assume)) {\n-\t\t\t\t\n-\t\t\t\t\tresult <- try (silent=FALSE, expr= {\n-\t\t\t\t\t\n-\t\t\t\t\t\trow.footnotes <- NULL\n-\n-\t\t\t\t\t\tassume.equal = assume[i]\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tf <- as.formula(paste(.v(variable), \"~\", .v(options$groupingVariable)))\n-\n-\t\t\t\t\t\tr <- t.test(f, data=dataset, alternative=testType, var.equal=assume.equal, conf.level=options$confidenceIntervalInterval)\n-\n-\t\t\t\t\t\tif (assume.equal) {\n-\t\t\t\t\t\n-\t\t\t\t\t\t\tlevene <- car::leveneTest(variableData, groupingData, \"mean\")\n-\t\t\t\t\t\t\t\n-\t\t\t\t\t\t\tif ( ! is.na(levene[1,3]) && levene[1,3] < .05) {\n-\t\t\t\t\t\t\n-\t\t\t\t\t\t\t\tfoot.index <- .addFootnote(footnotes, \"Levene's test is significant (p < .05), suggesting a violation of the equal variance assumption\")\n-\t\t\t\t\t\t\t\trow.footnotes <- list(p=list(foot.index))\n-\t\t\t\t\t\t\t}\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\t\tt <- as.numeric(r$statistic)\n-\t\t\t\t\t\tdf <- as.numeric(r$parameter)\n-\t\t\t\t\t\tp <- as.numeric(r$p.value)\n-\t\t\t\t\t\tm <- as.numeric(r$estimate[1]) - as.numeric(r$estimate[2])\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tns <- tapply(dataset[[.v(variable)]], dataset[[.v(options$groupingVariable)]], function(x)length(na.omit(x)))\n-\t\t\t\t\t\tms <- tapply(dataset[[.v(variable)]], dataset[[.v(options$groupingVariable)]], mean, na.rm = TRUE)\n-\t\t\t\t\t\tsds <- tapply(dataset[[.v(variable)]], dataset[[.v(options$groupingVariable)]], sd, na.rm = TRUE)\n-\t\t\t\t\t\t\t\t\t\t\t\t\n-\t\t\t\t\t\tsdPooled <- sqrt(((ns[1]-1)*sds[1]^2 + (ns[2]-1)*sds[2]^2) / (ns[1] + ns[2] - 2))\n-\t\t\t\t\t\td <- as.numeric((ms[1] - ms[2]) / sdPooled)\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tsed <- .clean(as.numeric(sqrt(sds[1]^2/ns[1] + sds[2]^2/ns[2])))\n-\t\t\t\t\t\tciLow <- .clean(r$conf.int[1])\n-\t\t\t\t\t\tciUp <- .clean(r$conf.int[2])\n-\t\t\t\t\t\t\t\t\t\t\t\n-#\t\t\t\t\t\tif (testType == \"two.sided\") {\n-#\t\t\t\t\t\n-#\t\t\t\t\t\t\tsed <- .clean()  # beckward approach - getting spread of CI and deviding by critical value for t\n-#\t\t\t\t\t\t\n-#\t\t\t\t\t\t} else if (testType == \"less\") {\n-#\t\t\t\t\t\n-#\t\t\t\t\t\t\tsed <- \"\"# .clean((ciUp - m) / (qt(options$confidenceIntervalInterval,r$parameter)))\n-#\t\t\t\t\t\t\n-#\t\t\t\t\t\t} else {\n-#\t\t\t\t\t\n-#\t\t\t\t\t\t\tsed <- \"\"# .clean((m - ciLow) / (qt(options$confidenceIntervalInterval,r$parameter)))\n-#\t\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\t\tlist(v=variable, variances=assumption[i], t=t, df=df, p=p, md=m, d=d,\n-\t\t\t\t\t\t\t lowerCI=ciLow, upperCI=ciUp, sed=sed, .footnotes=row.footnotes)\n-\t\t\t\t\t\t\n-\t\t\t\t\t})\n-\n-\t\t\t\t\tif (class(result) == \"try-error\") {\n-\t\t\t\t\t\n-\t\t\t\t\t\terrorMessage <- .extractErrorMessage(result)\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tif (errorMessage == \"missing value where TRUE/FALSE needed\" && any(is.finite(variableData) == FALSE)) {\n-\t\t\t\t\t\t\n-\t\t\t\t\t\t\terrorMessage <- \"t-statistic is undefined - the dependent variable contains infinity\"\n-\t\t\t\t\t\t\t\n-\t\t\t\t\t\t} else if (errorMessage == \"grouping factor must have exactly 2 levels\") {\n-\t\t\t\t\t\t\n-\t\t\t\t\t\t\t# We know that the grouping factor *does* have two levels, because we've checked this earlier on\n-\t\t\t\t\t\t\t# This error means that all of one factor has been excluded because of missing values in the dependent\n-\t\t\t\t\t\t\t\n-\t\t\t\t\t\t\terrorMessage <- \"t-statistic is undefined - the grouping variable contains less than two levels once missing values in the dependent are excluded\"\n-\t\t\t\t\t\t\t\n-\t\t\t\t\t\t} else if (errorMessage == \"data are essentially constant\") {\n-\t\t\t\t\t\t\n-\t\t\t\t\t\t\terrorMessage <- \"t-statistic is undefined - one or both levels of the dependent contains all the same value (zero variance)\"\n-\t\t\t\t\t\t\t\n-\t\t\t\t\t\t} else if (errorMessage == \"not enough observations\") {\n-\t\t\t\t\t\n-\t\t\t\t\t\t\terrorMessage <- \"t-statistic is undefined - one or both levels of the dependent contain too few observations\"\n-\t\t\t\t\t\t}\n-\t\t\t\t\t\t\n-\t\t\t\t\t\tindex <- .addFootnote(footnotes, errorMessage)\n-\t\t\t\t\n-\t\t\t\t\t\tresult <- list(v=variable, variances=assumption[i], t=\"NaN\", df=\"\", p=\"\", md=\"\",\n-\t\t\t\t\t\t\t\tlowerCI=\"\", upperCI=\"\", sed=\"\", .footnotes=list(t=list(index)))\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\tif (i == 1 && options$equalityOfVariances == \"reportBoth\")\n-\t\t\t\t\t\tresult[[\".isNewGroup\"]] <- TRUE\n-\t\t\t\t\n-\t\t\t\t\tttest.rows[[rowNo]] <- result\n-\t\t\t\t\trowNo <- rowNo + 1\n-\t\t\t\t}\n-\t\t\t}\n-\t\t\n-\t\t\tttest[[\"footnotes\"]] <- as.list(footnotes)\n-\t\t}\n-\t\t\n-\t}\n-\t\n-\tttest[[\"data\"]] <- ttest.rows\n-\t\n-\tttest\n+    ## if we actually have to do the test, and we have a grouping variable\n+    if (perform == \"run\" && groups != \"\") {\n+        levels <- base::levels(dataset[[ .v(groups) ]])\n+        \n+        ## if people don't know what a t-test is...\n+        if (length(levels) != 2) {\n+            descriptives[[\"error\"]] <- list(errorType = \"badData\")\n+            \n+        } else {\n+            \n+            rowNo <- 1\n+            groupingData <- dataset[[.v(groups)]]\n+\n+            ## do the whole loop as above again\n+            for (variable in variables) {\n+\n+                # if everything is alright, add stuff to data\n+                if (is_allright(variable, options, state, diff)) {\n+\n+                    state_dat <- state$results$descriptives$data\n+                    descriptivesVariables <- as.character(length(state_dat))\n+                    \n+                    for (i in seq_along(state_dat))\n+                        descriptivesVariables[i] <- state_dat[[i]]$variable\n+                    \n+                    indices <- which(descriptivesVariables == variable)\n+\n+                    data[[rowNo]] <- state_dat[[indices[1]]]\n+                    data[[rowNo]] <- state_dat[[indices[2]]]\n+\n+\t\t\t\t\trowNo <- rowNo + 2\n+                  \n+                } else {\n+                  \n+                    for (i in 1:2) {\n+                    \n+                      level <- levels[i]\n+                      variableData <- dataset[[.v(variable)]]\n+                    \n+                      groupData <- variableData[groupingData == level]\n+                      groupDataOm <- na.omit(groupData)\n+                    \n+                      if (class(groupDataOm) != \"factor\") {\n+                      \n+                          n <- .clean(length(groupDataOm))\n+                          mean <- .clean(mean(groupDataOm))\n+                          std <- .clean(sd(groupDataOm))\n+                          sem <- .clean(sd(groupDataOm) / sqrt(length(groupDataOm)))\n+                      \n+                          result <- list(variable = variable, group = level,\n+                                         N = n, mean = mean, sd = std, se = sem)\n+                      \n+                      } else {\n+                      \n+                        n <- .clean(length(groupDataOm))\n+                        result <- list(variable = variable, group = \"\",\n+                                       N = n, mean = \"\", sd = \"\", se = \"\")\n+                    }\n+                    \n+                    if (i == 1) {\n+                        result[[\".isNewGroup\"]] <- TRUE\n+                    }\n+                    \n+                    data[[rowNo]] <- result\n+                    rowNo <- rowNo + 1\n+                    }\n+                }\n+            }\n+        }\n+        descriptives[[\"status\"]] <- \"complete\"\n+    }\n \n+    descriptives[[\"data\"]] <- data\n+    descriptives\n }\n \n+\n .ttestIndependentSamplesInequalityOfVariances <- function(dataset, options, perform) {\n+    if (options$equalityOfVariancesTests == FALSE) return(NULL)\n+    \n+    levenes <- list(\"title\" = \"Test of Equality of Variances (Levene's)\")\n+    footnotes <- .newFootnotes()\n+    \n+    ## setup table for Levene's test\n+    fields <- list(list(name = \"variable\", title = \"\", type = \"string\"),\n+                   list(name = \"F\", type = \"number\", format = \"sf:4;dp:3\"),\n+                   list(name = \"df\", type = \"integer\"),\n+                   list(name = \"p\", type = \"number\", format = \"dp:3;p:.001\"))\n+    \n+    levenes[[\"schema\"]] <- list(fields = fields)\n+    \n+    data <- list()\n+    variables <- options$variables\n+    groups <- options$groupingVariable\n+    if (length(variables) == 0) variables <- \".\"\n+    \n+    for (variable in variables) {\n+        data[[length(data) + 1]] <- list(variable = variable)\n+    }\n+    \n+    if (perform == \"run\" && groups != \"\") {\n \n-\tif (options$equalityOfVariancesTests == FALSE)\n-\t\treturn(NULL)\n-\t\t\n-\tlevenes <- list()\n-\tfootnotes <- .newFootnotes()\n-\n-\tlevenes[[\"title\"]] <- \"Test of Equality of Variances (Levene's)\"\n-\t\n-\tfields <- list(\n-\t\tlist(name=\"variable\", title=\"\", type=\"string\"),\n-\t\tlist(name=\"F\", type=\"number\", format=\"sf:4;dp:3\"),\n-\t\tlist(name=\"df\", type=\"integer\"),\n-\t\tlist(name=\"p\", type=\"number\", format=\"dp:3;p:.001\"))\n-\n-\tlevenes[[\"schema\"]] <- list(fields=fields)\n-\t\n-\tdata <- list()\n-\t\n-\tvariables <- options[[\"variables\"]]\n-\tif (length(variables) == 0)\n-\t\tvariables <- \".\"\n-\t\n-\tfor (variable in variables)\n-\t\tdata[[length(data)+1]] <- list(variable=variable)\n-\t\n-\tif (perform == \"run\" && options$groupingVariable != \"\") {\n-\t\n-\t\tlevels <- base::levels(dataset[[ .v(options$groupingVariable) ]])\n-\t\t\n-\t\tif (length(levels) != 2) {\n-\t\t\n-\t\t\tlevenes[[\"error\"]] <- list(errorType=\"badData\")\n-\t\t\t\n-\t\t} else {\n-\t\n-\t\t\trowNo <- 1\n-\n-\t\t\tfor (variable in options[[\"variables\"]]) {\n-\t\t\n-\t\t\t\tresult <- try (silent=TRUE, expr= {\n-\n-\t\t\t\t\tlevene <- car::leveneTest(dataset[[ .v(variable) ]], dataset[[ .v(options$groupingVariable) ]], \"mean\")\n-\n-\t\t\t\t\tF  <- .clean(levene[1,\"F value\"])\n-\t\t\t\t\tdf <- .clean(levene[1,\"Df\"])\n-\t\t\t\t\tp  <- .clean(levene[1,\"Pr(>F)\"])\n-\t\t\n-\t\t\t\t\trow <- list(variable=variable, F=F, df=df, p=p)\n-\t\t\t\t\t\n-\t\t\t\t\tif (is.na(levene[1,\"F value\"])) {\n-\t\t\t\t\t\n-\t\t\t\t\t\tindex <- .addFootnote(footnotes, \"F-statistic could not be calculated\")\n-\t\t\t\t\t\trow[[\".footnotes\"]] <- list(F=list(index))\n-\t\t\t\t\t}\n-\t\t\t\t\t\n-\t\t\t\t\trow\n-\t\t\t\t})\n-\n-\t\t\t\tif (class(result) == \"try-error\")\n-\t\t\t\t\tresult <- list(variable=variable, F=\"\", df=\"\", p=\"\")\n-\t\n-\t\t\t\tdata[[rowNo]] <- result\n-\t\t\t\trowNo <- rowNo + 1\n-\t\t\t}\n-\t\t}\n-\t\n-\t}\n-\t\n-\tlevenes[[\"data\"]] <- data\n-\tlevenes[[\"footnotes\"]] <- as.list(footnotes)\n-\n-\tlevenes\n+        levels <- base::levels(dataset[[ .v(groups) ]])\n+        \n+        if (length(levels) != 2) {\n+            levenes[[\"error\"]] <- list(errorType = \"badData\")\n+            \n+        } else {\n+            \n+            rowNo <- 1\n+            \n+            for (variable in variables) {\n+                \n+                result <- try(silent = TRUE, expr = {\n+                  \n+                  levene <- car::leveneTest(dataset[[ .v(variable) ]],\n+                                            dataset[[ .v(groups) ]], \"mean\")\n+                  \n+                  F <- .clean(levene[1, \"F value\"])\n+                  df <- .clean(levene[1, \"Df\"])\n+                  p <- .clean(levene[1, \"Pr(>F)\"])\n+                  \n+                  row <- list(variable = variable, F = F, df = df, p = p)\n+                  \n+                  if (is.na(levene[1, \"F value\"])) {\n+                      note <- \"F-statistic could not be calculated\"\n+                      index <- .addFootnote(footnotes, note)\n+                      row[[\".footnotes\"]] <- list(F = list(index))\n+                  }\n+                  \n+                  row\n+                })\n+                \n+                if (class(result) == \"try-error\") {\n+                  result <- list(variable = variable, F = \"\", df = \"\", p = \"\")\n+                }\n+                \n+                data[[rowNo]] <- result\n+                rowNo <- rowNo + 1\n+            }\n+        }\n+    }\n+    levenes[[\"data\"]] <- data\n+    levenes[[\"footnotes\"]] <- as.list(footnotes)\n+    levenes\n }\n \n-.independentSamplesTTestDescriptivesPlot <- function(dataset, options, perform) {\n \n-\tdescriptivesPlotList <- list()\n-\n-\tif (perform == \"run\" && length(options$variables) > 0 && options$groupingVariable != \"\") {\n-\t\t\t\t\n-\t\tbase_breaks_x <- function(x){\n-\t\t\tb <- unique(as.numeric(x))\n-\t\t\td <- data.frame(y=-Inf, yend=-Inf, x=min(b), xend=max(b))\n-\t\t\tlist(ggplot2::geom_segment(data=d, ggplot2::aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE, size = 1))\n-\t\t}\n-\n-\t\tbase_breaks_y <- function(x){\n-\t\t\tci.pos <- c(x[,\"dependent\"]-x[,\"ci\"],x[,\"dependent\"]+x[,\"ci\"])\n-\t\t\tb <- pretty(ci.pos)\n-\t\t\td <- data.frame(x=-Inf, xend=-Inf, y=min(b), yend=max(b))\n-\t\t\tlist(ggplot2::geom_segment(data=d, ggplot2::aes(x=x, y=y, xend=xend, yend=yend), inherit.aes=FALSE, size = 1),\n-\t\t\t\tggplot2::scale_y_continuous(breaks=c(min(b),max(b))))\n-\t\t}\n-\t\t\t\t\n-\t\tfor (var in .indices(options$variables)) {\n-\t\t\t\n-\t\t\tdescriptivesPlot <- list()\n-\t\t\t\n-\t\t\tdescriptivesPlot[[\"title\"]] <- \"\"\n-\t\t\tdescriptivesPlot[[\"width\"]] <- options$plotWidth\n-\t\t\tdescriptivesPlot[[\"height\"]] <- options$plotHeight\n-\t\t\tdescriptivesPlot[[\"custom\"]] <- list(width=\"plotWidth\", height=\"plotHeight\")\n-\t\t\t\n-\t\t\tsummaryStat <- .summarySE(as.data.frame(dataset), measurevar = .v(options$variables[var]), groupvars = .v(options$groupingVariable), \n-\t\t\t\t\t\t   conf.interval = options$descriptivesPlotsConfidenceInterval, na.rm = TRUE, .drop = FALSE)\n-\t\t\t\n-\t\t\tcolnames(summaryStat)[which(colnames(summaryStat) == .v(options$variables[var]))] <- \"dependent\"\t\t\t\t\t\t\t\t\t\t\n-\t\t\tcolnames(summaryStat)[which(colnames(summaryStat) == .v(options$groupingVariable))] <- \"groupingVariable\"\n-\t\t\t\n-\t\t\tpd <- ggplot2::position_dodge(.2)\n-\t\t\t\t\t\t\n-\t\t\tp <- ggplot2::ggplot(summaryStat, ggplot2::aes(x=groupingVariable, y=dependent, group=1)) +\n-\t\t\t\t ggplot2::geom_errorbar(ggplot2::aes(ymin=ciLower, ymax=ciUpper), colour=\"black\", width=.2, position=pd) +\n-\t\t\t\t ggplot2::geom_line(position=pd, size = .7) + \n-\t\t\t\t ggplot2::geom_point(position=pd, size=4) +\n-\t\t\t\t ggplot2::ylab(unlist(options$variables[var])) +\n-\t\t\t\t ggplot2::xlab(options$groupingVariable) +\n-\t\t\t\t ggplot2::theme_bw() +\n-\t\t\t\t ggplot2::ggtitle(options$variables[var]) +\n-\t\t\t\t ggplot2::theme(panel.grid.minor=ggplot2::element_blank(), plot.title = ggplot2::element_text(size=18),\n-\t\t\t\t\tpanel.grid.major=ggplot2::element_blank(),\n-\t\t\t\t\taxis.title.x = ggplot2::element_text(size=18,vjust=-.2), axis.title.y = ggplot2::element_text(size=18,vjust=-1),\n-\t\t\t\t\taxis.text.x = ggplot2::element_text(size=15), axis.text.y = ggplot2::element_text(size=15),\n-\t\t\t\t\tpanel.background = ggplot2::element_rect(fill = 'transparent', colour = NA),\n-\t\t\t\t\tplot.background = ggplot2::element_rect(fill = 'transparent', colour = NA),\n-\t\t\t\t\tlegend.background = ggplot2::element_rect(fill = 'transparent', colour = NA),\n-\t\t\t\t\tpanel.border = ggplot2::element_blank(), axis.line = ggplot2::element_blank(),\n-\t\t\t\t\tlegend.key = ggplot2::element_blank(),\n-\t\t\t\t\tlegend.title = ggplot2::element_text(size=12),\n-\t\t\t\t\tlegend.text = ggplot2::element_text(size = 12),\n-\t\t\t\t\taxis.ticks = ggplot2::element_line(size = 0.5),\n-\t\t\t\t\taxis.ticks.margin = grid::unit(1,\"mm\"),\n-\t\t\t\t\taxis.ticks.length = grid::unit(3, \"mm\"),\n-\t\t\t\t\tplot.margin = grid::unit(c(.5,0,.5,.5), \"cm\")) +\n-\t\t\t\t base_breaks_y(summaryStat) +\n-\t\t\t\t base_breaks_x(summaryStat$groupingVariable)\n-\t\t\t\t\t\t\t\t\n-\t\t\timage <- .beginSaveImage(options$plotWidth, options$plotHeight)\n-\t\t\tprint(p)\n-\t\t\tcontent <- .endSaveImage(image)\n-\n-\t\t\tdescriptivesPlot[[\"data\"]] <- content\n-\n-\t\t\tdescriptivesPlotList[[var]] <- descriptivesPlot\n-\t\t\t\n-\t\t}\n-\t\t\n-\t} else {\n+.ttestIndependentSamplesNormalityTest <- function(dataset, options, perform) {\n+    if (options$normalityTests == FALSE) return(NULL)\n+    \n+    normalityTests <- list(\"title\" = \"Test of Normality (Shapiro-Wilk)\")\n+    \n+    ## these are the table fields associated with the normality test\n+    fields <- list(\n+        list(name = \"dep\", type = \"string\", title = \"\", combine = TRUE), \n+        list(name = \"lev\", type = \"string\", title = \"\"),\n+        list(name = \"W\", title = \"W\", type = \"number\", format = \"sf:4;dp:3\"),\n+        list(name = \"p\", title = \"p\", type = \"number\", format = \"dp:3;p:.001\")\n+    )\n+    \n+    normalityTests[[\"schema\"]] <- list(fields = fields)\n+    \n+    footnotes <- .newFootnotes()\n+    .addFootnote(footnotes, symbol = \"<em>Note.</em>\",\n+                 text = \"Significant results indicate a deviation from normality\")\n+    \n+    ## for a independent t-test, we need to check both group vectors for normality\n+    normalityTests.results <- list()\n+    \n+    variables <- options$variables\n+    factor <- options$groupingVariable\n+    levels <- levels(dataset[[.v(factor)]])\n \n-\t\tfor (var in .indices(options$variables)) {\n+    if (length(variables) == 0) variables = \".\"\n+    if (length(levels) == 0) levels = c(\".\", \".\")\n+    \n+    for (variable in variables) {\n+        count <- 0\n+        \n+        ## there will be maximal two levels\n+        for (level in levels) {\n+            count <- count + 1\n+           \n+            ## if everything looks fine, and we are ready to run\n+            if (perform == \"run\" && length(variables) > 0 && !is.null(levels)) {\n+\n+                ## get the dependent variable at a certain factor level\n+                data <- na.omit(dataset[[.v(variable)]][dataset[[.v(factor)]] == level])\n+                \n+                row.footnotes <- NULL\n+                error <- FALSE\n+                \n+                if (length(data) < 3) {\n+                    err <- \"Too few datapoints (N < 3) to compute statistic reliably\"\n+                    foot.index <- .addFootnote(footnotes, err)\n+                    row.footnotes <- list(W = list(foot.index), p = list(foot.index))\n+                    error <- TRUE\n+                  \n+                } else if (length(data) > 5000) {\n+                    err <- \"Too many datapoints (N > 5000) to compute statistic reliably\"\n+                    foot.index <- .addFootnote(footnotes, err)\n+                    row.footnotes <- list(W = list(foot.index), p = list(foot.index))\n+                    error <- TRUE\n+                }\n+                \n+                ## if the user did everything correctly :)\n+                if (!error) {","path":"JASP-Engine/JASP/R/ttestindependentsamples.R","position":1216,"original_position":1216,"commit_id":"205e7bc030a0eb8c28667e7855b6cd08c7df54a4","original_commit_id":"205e7bc030a0eb8c28667e7855b6cd08c7df54a4","user":{"login":"jonathon-love","id":3240247,"avatar_url":"https://avatars.githubusercontent.com/u/3240247?v=3","gravatar_id":"","url":"https://api.github.com/users/jonathon-love","html_url":"https://github.com/jonathon-love","followers_url":"https://api.github.com/users/jonathon-love/followers","following_url":"https://api.github.com/users/jonathon-love/following{/other_user}","gists_url":"https://api.github.com/users/jonathon-love/gists{/gist_id}","starred_url":"https://api.github.com/users/jonathon-love/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jonathon-love/subscriptions","organizations_url":"https://api.github.com/users/jonathon-love/orgs","repos_url":"https://api.github.com/users/jonathon-love/repos","events_url":"https://api.github.com/users/jonathon-love/events{/privacy}","received_events_url":"https://api.github.com/users/jonathon-love/received_events","type":"User","site_admin":false},"body":"good practice to put spaces around the exclamation mark\r\n\r\n    if ( ! error) {\r\n\r\nit is easy to miss the exclamation mark (depending on the editor, syntax highlighting, etc. this often isn't bad, but we like to accommodate the general case).\r\n\r\nsome people go further and do the:\r\n\r\n    if (error == FALSE) {\r\n\r\nto be extra explicit (but not me)","created_at":"2015-09-19T17:15:00Z","updated_at":"2015-09-19T17:15:00Z","html_url":"https://github.com/jasp-stats/jasp-desktop/pull/993#discussion_r39921533","pull_request_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993","_links":{"self":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/comments/39921533"},"html":{"href":"https://github.com/jasp-stats/jasp-desktop/pull/993#discussion_r39921533"},"pull_request":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993"}}},"pull_request":{"url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993","id":45480180,"html_url":"https://github.com/jasp-stats/jasp-desktop/pull/993","diff_url":"https://github.com/jasp-stats/jasp-desktop/pull/993.diff","patch_url":"https://github.com/jasp-stats/jasp-desktop/pull/993.patch","issue_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/993","number":993,"state":"open","locked":false,"title":"refactored ttests and added non-parametric alternatives","user":{"login":"dostodabsi","id":6568110,"avatar_url":"https://avatars.githubusercontent.com/u/6568110?v=3","gravatar_id":"","url":"https://api.github.com/users/dostodabsi","html_url":"https://github.com/dostodabsi","followers_url":"https://api.github.com/users/dostodabsi/followers","following_url":"https://api.github.com/users/dostodabsi/following{/other_user}","gists_url":"https://api.github.com/users/dostodabsi/gists{/gist_id}","starred_url":"https://api.github.com/users/dostodabsi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dostodabsi/subscriptions","organizations_url":"https://api.github.com/users/dostodabsi/orgs","repos_url":"https://api.github.com/users/dostodabsi/repos","events_url":"https://api.github.com/users/dostodabsi/events{/privacy}","received_events_url":"https://api.github.com/users/dostodabsi/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-09-19T17:00:18Z","updated_at":"2015-09-19T17:15:00Z","closed_at":null,"merged_at":null,"merge_commit_sha":"4952b2e4b3e7763e7dafb9988bf7689bfc1c5792","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993/commits","review_comments_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993/comments","review_comment_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/comments{/number}","comments_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/993/comments","statuses_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/statuses/205e7bc030a0eb8c28667e7855b6cd08c7df54a4","head":{"label":"dostodabsi:development","ref":"development","sha":"205e7bc030a0eb8c28667e7855b6cd08c7df54a4","user":{"login":"dostodabsi","id":6568110,"avatar_url":"https://avatars.githubusercontent.com/u/6568110?v=3","gravatar_id":"","url":"https://api.github.com/users/dostodabsi","html_url":"https://github.com/dostodabsi","followers_url":"https://api.github.com/users/dostodabsi/followers","following_url":"https://api.github.com/users/dostodabsi/following{/other_user}","gists_url":"https://api.github.com/users/dostodabsi/gists{/gist_id}","starred_url":"https://api.github.com/users/dostodabsi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dostodabsi/subscriptions","organizations_url":"https://api.github.com/users/dostodabsi/orgs","repos_url":"https://api.github.com/users/dostodabsi/repos","events_url":"https://api.github.com/users/dostodabsi/events{/privacy}","received_events_url":"https://api.github.com/users/dostodabsi/received_events","type":"User","site_admin":false},"repo":{"id":42702889,"name":"jasp-desktop","full_name":"dostodabsi/jasp-desktop","owner":{"login":"dostodabsi","id":6568110,"avatar_url":"https://avatars.githubusercontent.com/u/6568110?v=3","gravatar_id":"","url":"https://api.github.com/users/dostodabsi","html_url":"https://github.com/dostodabsi","followers_url":"https://api.github.com/users/dostodabsi/followers","following_url":"https://api.github.com/users/dostodabsi/following{/other_user}","gists_url":"https://api.github.com/users/dostodabsi/gists{/gist_id}","starred_url":"https://api.github.com/users/dostodabsi/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/dostodabsi/subscriptions","organizations_url":"https://api.github.com/users/dostodabsi/orgs","repos_url":"https://api.github.com/users/dostodabsi/repos","events_url":"https://api.github.com/users/dostodabsi/events{/privacy}","received_events_url":"https://api.github.com/users/dostodabsi/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/dostodabsi/jasp-desktop","description":"JASP aims to be a complete statistical package for both Bayesian and Frequentist statistical methods, that is easy to use and familiar to users of SPSS","fork":true,"url":"https://api.github.com/repos/dostodabsi/jasp-desktop","forks_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/forks","keys_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/teams","hooks_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/hooks","issue_events_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/issues/events{/number}","events_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/events","assignees_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/assignees{/user}","branches_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/branches{/branch}","tags_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/tags","blobs_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/git/refs{/sha}","trees_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/statuses/{sha}","languages_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/languages","stargazers_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/stargazers","contributors_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/contributors","subscribers_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/subscribers","subscription_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/subscription","commits_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/commits{/sha}","git_commits_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/git/commits{/sha}","comments_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/comments{/number}","issue_comment_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/issues/comments{/number}","contents_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/contents/{+path}","compare_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/merges","archive_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/downloads","issues_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/issues{/number}","pulls_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/pulls{/number}","milestones_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/milestones{/number}","notifications_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/labels{/name}","releases_url":"https://api.github.com/repos/dostodabsi/jasp-desktop/releases{/id}","created_at":"2015-09-18T06:04:45Z","updated_at":"2015-09-18T06:04:46Z","pushed_at":"2015-09-19T16:58:57Z","git_url":"git://github.com/dostodabsi/jasp-desktop.git","ssh_url":"git@github.com:dostodabsi/jasp-desktop.git","clone_url":"https://github.com/dostodabsi/jasp-desktop.git","svn_url":"https://github.com/dostodabsi/jasp-desktop","homepage":"jasp-stats.org","size":5607,"stargazers_count":0,"watchers_count":0,"language":"R","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"development"}},"base":{"label":"jasp-stats:development","ref":"development","sha":"3d2a70f19add2ad830ed7c356be4f4e9f5726b02","user":{"login":"jasp-stats","id":4589101,"avatar_url":"https://avatars.githubusercontent.com/u/4589101?v=3","gravatar_id":"","url":"https://api.github.com/users/jasp-stats","html_url":"https://github.com/jasp-stats","followers_url":"https://api.github.com/users/jasp-stats/followers","following_url":"https://api.github.com/users/jasp-stats/following{/other_user}","gists_url":"https://api.github.com/users/jasp-stats/gists{/gist_id}","starred_url":"https://api.github.com/users/jasp-stats/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jasp-stats/subscriptions","organizations_url":"https://api.github.com/users/jasp-stats/orgs","repos_url":"https://api.github.com/users/jasp-stats/repos","events_url":"https://api.github.com/users/jasp-stats/events{/privacy}","received_events_url":"https://api.github.com/users/jasp-stats/received_events","type":"Organization","site_admin":false},"repo":{"id":10426982,"name":"jasp-desktop","full_name":"jasp-stats/jasp-desktop","owner":{"login":"jasp-stats","id":4589101,"avatar_url":"https://avatars.githubusercontent.com/u/4589101?v=3","gravatar_id":"","url":"https://api.github.com/users/jasp-stats","html_url":"https://github.com/jasp-stats","followers_url":"https://api.github.com/users/jasp-stats/followers","following_url":"https://api.github.com/users/jasp-stats/following{/other_user}","gists_url":"https://api.github.com/users/jasp-stats/gists{/gist_id}","starred_url":"https://api.github.com/users/jasp-stats/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jasp-stats/subscriptions","organizations_url":"https://api.github.com/users/jasp-stats/orgs","repos_url":"https://api.github.com/users/jasp-stats/repos","events_url":"https://api.github.com/users/jasp-stats/events{/privacy}","received_events_url":"https://api.github.com/users/jasp-stats/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/jasp-stats/jasp-desktop","description":"JASP aims to be a complete statistical package for both Bayesian and Frequentist statistical methods, that is easy to use and familiar to users of SPSS","fork":false,"url":"https://api.github.com/repos/jasp-stats/jasp-desktop","forks_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/forks","keys_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/keys{/key_id}","collaborators_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/teams","hooks_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/hooks","issue_events_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/events{/number}","events_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/events","assignees_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/assignees{/user}","branches_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/branches{/branch}","tags_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/tags","blobs_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/git/refs{/sha}","trees_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/git/trees{/sha}","statuses_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/statuses/{sha}","languages_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/languages","stargazers_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/stargazers","contributors_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/contributors","subscribers_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/subscribers","subscription_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/subscription","commits_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/commits{/sha}","git_commits_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/git/commits{/sha}","comments_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/comments{/number}","issue_comment_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/comments{/number}","contents_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/contents/{+path}","compare_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/compare/{base}...{head}","merges_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/merges","archive_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/downloads","issues_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues{/number}","pulls_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls{/number}","milestones_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/milestones{/number}","notifications_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/labels{/name}","releases_url":"https://api.github.com/repos/jasp-stats/jasp-desktop/releases{/id}","created_at":"2013-06-01T19:05:12Z","updated_at":"2015-09-18T19:33:01Z","pushed_at":"2015-09-19T17:00:18Z","git_url":"git://github.com/jasp-stats/jasp-desktop.git","ssh_url":"git@github.com:jasp-stats/jasp-desktop.git","clone_url":"https://github.com/jasp-stats/jasp-desktop.git","svn_url":"https://github.com/jasp-stats/jasp-desktop","homepage":"jasp-stats.org","size":9507,"stargazers_count":82,"watchers_count":82,"language":"R","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":37,"mirror_url":null,"open_issues_count":75,"forks":37,"open_issues":75,"watchers":82,"default_branch":"development"}},"_links":{"self":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993"},"html":{"href":"https://github.com/jasp-stats/jasp-desktop/pull/993"},"issue":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/993"},"comments":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/issues/993/comments"},"review_comments":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993/comments"},"review_comment":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/pulls/993/commits"},"statuses":{"href":"https://api.github.com/repos/jasp-stats/jasp-desktop/statuses/205e7bc030a0eb8c28667e7855b6cd08c7df54a4"}}}}