diff --git a/src/backend/hypothesis_test/HypothesisTest.h b/src/backend/hypothesis_test/HypothesisTest.h
--- a/src/backend/hypothesis_test/HypothesisTest.h
+++ b/src/backend/hypothesis_test/HypothesisTest.h
@@ -64,13 +64,14 @@
QString testName();
QString statsTable();
- void performTwoSampleTTest();
- void performTwoSampleIndependentTTest(bool equal_variance);
+ void performTwoSampleIndependentTTest(bool categorical_variable, bool equal_variance);
void performTwoSamplePairedTTest();
- void PerformOneSampleTTest();
+ void performOneSampleTTest();
void performTwoSampleIndependentZTest();
void performTwoSamplePairedZTest();
- void PerformOneSampleZTest();
+ void performOneSampleZTest();
+
+ void performLeveneTest(bool categorical_variable);
//virtual methods
// QIcon icon() const override;
QMenu* createContextMenu() override;
diff --git a/src/backend/hypothesis_test/HypothesisTest.cpp b/src/backend/hypothesis_test/HypothesisTest.cpp
--- a/src/backend/hypothesis_test/HypothesisTest.cpp
+++ b/src/backend/hypothesis_test/HypothesisTest.cpp
@@ -107,9 +107,9 @@
return d->m_stats_table;
}
-void HypothesisTest::performTwoSampleIndependentTTest(bool equal_variance) {
+void HypothesisTest::performTwoSampleIndependentTTest(bool categorical_variable, bool equal_variance) {
d->m_currTestName = "
Two Sample Independent T Test
";
- d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestT, equal_variance);
+ d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestT, categorical_variable, equal_variance);
}
void HypothesisTest::performTwoSamplePairedTTest() {
@@ -117,9 +117,9 @@
d->performTwoSamplePairedTest(HypothesisTestPrivate::TestT);
}
-void HypothesisTest::PerformOneSampleTTest() {
+void HypothesisTest::performOneSampleTTest() {
d->m_currTestName = "One Sample T Test
";
- d->PerformOneSampleTest(HypothesisTestPrivate::TestT);
+ d->performOneSampleTest(HypothesisTestPrivate::TestT);
}
void HypothesisTest::performTwoSampleIndependentZTest() {
@@ -132,13 +132,15 @@
d->performTwoSamplePairedTest(HypothesisTestPrivate::TestZ);
}
-void HypothesisTest::PerformOneSampleZTest() {
+void HypothesisTest::performOneSampleZTest() {
d->m_currTestName = "One Sample Z Test
";
- d->PerformOneSampleTest(HypothesisTestPrivate::TestZ);
+ d->performOneSampleTest(HypothesisTestPrivate::TestZ);
}
-
-
+void HypothesisTest::performLeveneTest(bool categorical_variable) {
+ d->m_currTestName = "Levene Test for Equality of Variance
";
+ d->performLeveneTest(categorical_variable);
+}
/******************************************************************************
* Private Implementations
@@ -177,7 +179,7 @@
/**************************Two Sample Independent *************************************/
-void HypothesisTestPrivate::performTwoSampleIndependentTest(TestType test, bool equal_variance) {
+void HypothesisTestPrivate::performTwoSampleIndependentTest(TestType test,bool categorical_variable, bool equal_variance) {
QString test_name;
double value;
@@ -197,7 +199,7 @@
QString col1_name = m_columns[0]->name();
QString col2_name = m_columns[1]->name();
- if (m_columns[0]->columnMode() == AbstractColumn::Integer || m_columns[0]->columnMode() == AbstractColumn::Numeric) {
+ if (!categorical_variable && (m_columns[0]->columnMode() == AbstractColumn::Integer || m_columns[0]->columnMode() == AbstractColumn::Numeric)) {
for (int i = 0; i < 2; i++) {
findStats(m_columns[i], n[i], sum[i], mean[i], std[i]);
@@ -208,23 +210,40 @@
}
}
} else {
- ErrorType error_code = findStatsCategorical(m_columns[0], m_columns[1], n, sum, mean, std, col1_name, col2_name);
+ QMap col_name;
+ int np;
+ int total_rows;
+
+ countPartitions(m_columns[0], np, total_rows);
+ if (np != 2) {
+ printError( i18n("Number of Categorical Variable in Column %1 is not equal to 2", m_columns[0]->name()));
+ emit q->changed();
+ return;
+ }
+
+ ErrorType error_code = findStatsCategorical(m_columns[0], m_columns[1], n, sum, mean, std, col_name, np, total_rows);
+
switch (error_code) {
case ErrorUnqualSize: {
printError( i18n("Unequal size between Column %1 and Column %2", m_columns[0]->name(), m_columns[1]->name()));
emit q->changed();
return;
- } case ErrorNotTwoCategoricalVariables: {
- printError( i18n("Number of Categorical Variable in Column %1 is not equal to 2", m_columns[0]->name()));
- emit q->changed();
- return;
- } case ErrorEmptyColumn: {
+ }case ErrorEmptyColumn: {
printError("At least one of selected column is empty");
emit q->changed();
return;
} case NoError:
break;
}
+
+ QMapIterator i(col_name);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value() == 1)
+ col1_name = i.key();
+ else
+ col2_name = i.key();
+ }
}
QVariant row_major[] = {"", "N", "Sum", "Mean", "Std",
@@ -316,9 +335,6 @@
return;
} case NoError:
break;
- default:
- emit q->changed();
- return;
}
if (n == -1) {
@@ -371,7 +387,7 @@
/******************************** One Sample ***************************************/
-void HypothesisTestPrivate::PerformOneSampleTest(TestType test) {
+void HypothesisTestPrivate::performOneSampleTest(TestType test) {
QString test_name;
double value;
int df = 0;
@@ -401,7 +417,7 @@
return;
} case NoError:
break;
- default: {
+ case ErrorEmptyColumn: {
emit q->changed();
return;
}
@@ -442,6 +458,232 @@
}
+/**************************************Levene Test****************************************/
+void HypothesisTestPrivate::performLeveneTest(bool categorical_variable) {
+ QString test_name;
+ double f_value;
+ int df = 0; // degree of freedom
+ double p_value = 0;
+ int np = 0; // number of partitions
+ int n = 0;
+ int total_rows = 0;
+ clearGlobalVariables();
+
+ if (m_columns.size() != 2) {
+ printError("Inappropriate number of columns selected");
+ emit q->changed();
+ return;
+ }
+
+ if (!categorical_variable && (m_columns[0]->columnMode() == AbstractColumn::Integer || m_columns[0]->columnMode() == AbstractColumn::Numeric))
+ np = m_columns.size();
+ else
+ countPartitions(m_columns[0], np, n);
+
+ if (np < 2) {
+ printError("select atleast two columns/ classes");
+ emit q->changed();
+ return;
+ }
+
+ double* yi_bar = new double[np];
+ double* zi_bar = new double[np];
+ double zi_bar_bar = 0;
+ double* ni = new double[np];
+
+ for (int i = 0; i < np; i++) {
+ yi_bar[i] = 0;
+ zi_bar[i] = 0;
+ ni[i] = 0;
+ }
+
+ QString* col_names = new QString[np];
+ if (!categorical_variable && (m_columns[0]->columnMode() == AbstractColumn::Integer || m_columns[0]->columnMode() == AbstractColumn::Numeric)) {
+ total_rows = m_columns[0]->rowCount();
+
+ double value = 0;
+ for (int j = 0; j < total_rows; j++) {
+ int number_nan_cols = 0;
+ for (int i = 0; i < np; i++) {
+ value = m_columns[i]->valueAt(j);
+ if (std::isnan(value)) {
+ number_nan_cols++;
+ continue;
+ }
+ yi_bar[i] += value;
+ ni[i]++;
+ n++;
+ }
+ if (number_nan_cols == np) {
+ total_rows = j;
+ break;
+ }
+ }
+
+ for (int i = 0; i < np; i++) {
+ if (ni[i] > 0)
+ yi_bar[i] = yi_bar[i] / ni[i];
+ }
+
+ for (int j = 0; j < total_rows; j++) {
+ for (int i = 0; i < np; i++) {
+ value = m_columns[i]->valueAt(j);
+ if (!(std::isnan(value)))
+ zi_bar[i] += abs(value - yi_bar[i]);
+ }
+ }
+
+ for (int i = 0; i < np; i++) {
+ zi_bar_bar += zi_bar[i];
+ if (ni[i] > 0)
+ zi_bar[i] = zi_bar[i] / ni[i];
+ }
+
+ zi_bar_bar = zi_bar_bar / n;
+
+ double numerator_value = 0;
+ double denominator_value = 0;
+
+ for (int j = 0; j < total_rows; j++) {
+ for (int i = 0; i < np; i++) {
+ value = m_columns[i]->valueAt(j);
+ if (!(std::isnan(value))) {
+ double zij = abs(value - yi_bar[i]);
+ denominator_value += qPow( (zij - zi_bar[i]), 2);
+ }
+ }
+ }
+
+ for (int i = 0; i < np; i++) {
+ col_names[i] = m_columns[i]->name();
+ numerator_value += ni[i]*qPow( (zi_bar[i]-zi_bar_bar), 2);
+ }
+
+ f_value = ((n - np) / (np - 1)) * (numerator_value / denominator_value);
+
+// qDebug() << "n is " << n;
+// qDebug() << "fvalue is " << f_value;
+// qDebug() << "numerator is " << numerator_value;
+// qDebug() << "denominator is " << denominator_value;
+
+ }
+ else {
+ QMap classname_to_index;
+
+ AbstractColumn::ColumnMode original_col_mode = m_columns[0]->columnMode();
+ m_columns[0]->setColumnMode(AbstractColumn::Text);
+
+ int partition_number = 1;
+ QString name;
+ double value;
+ int class_index;
+
+ for (int j = 0; j < n; j++) {
+ name = m_columns[0]->textAt(j);
+ value = m_columns[1]->valueAt(j);
+
+ if (std::isnan(value)) {
+ n = j;
+ break;
+ }
+
+ if (classname_to_index[name] == 0) {
+ classname_to_index[name] = partition_number;
+ partition_number++;
+ }
+
+ class_index = classname_to_index[name]-1;
+ ni[class_index]++;
+ yi_bar[class_index] += value;
+ }
+
+ for (int i = 0; i < np; i++) {
+ if (ni[i] > 0)
+ yi_bar[i] = yi_bar[i] / ni[i];
+ }
+
+ for (int j = 0; j < n; j++) {
+ name = m_columns[0]->textAt(j);
+ value = m_columns[1]->valueAt(j);
+ class_index = classname_to_index[name] - 1;
+ zi_bar[class_index] += abs(value - yi_bar[class_index]);
+ }
+
+ for (int i = 0; i < np; i++) {
+ zi_bar_bar += zi_bar[i];
+ zi_bar[i] = zi_bar[i] / ni[i];
+ }
+
+ zi_bar_bar = zi_bar_bar / n;
+
+ double numerator_value = 0;
+ double denominator_value = 0;
+
+ for (int j = 0; j < n; j++) {
+ name = m_columns[0]->textAt(j);
+ value = m_columns[1]->valueAt(j);
+ class_index = classname_to_index[name] - 1;
+ double zij = abs(value - yi_bar[class_index]);
+ denominator_value += qPow( (zij - zi_bar[class_index]), 2);
+ }
+
+ for (int i = 0; i < np; i++)
+ numerator_value += ni[i]*qPow( (zi_bar[i]-zi_bar_bar), 2);
+
+ f_value = ((n - np) / (np - 1)) * (numerator_value / denominator_value);
+
+// qDebug() << "n is " << n;
+// qDebug() << "fvalue is " << f_value;
+// qDebug() << "numerator is " << numerator_value;
+// qDebug() << "denominator is " << denominator_value;
+
+ QMapIterator i(classname_to_index);
+ while (i.hasNext()) {
+ i.next();
+ col_names[i.value()-1] = i.key();
+ }
+ m_columns[0]->setColumnMode(original_col_mode);
+ }
+
+ df = n - np;
+
+ int row_count = np+1;
+ int column_count = 4;
+
+
+ QVariant* row_major = new QVariant[row_count*column_count];
+ // header data;
+ row_major[0] = ""; row_major[1] = "Ni"; row_major[2] = "Yi_bar"; row_major[3] = "Zi_bar";
+
+ // table data
+ for (int row_i = 1; row_i < row_count; row_i++) {
+ row_major[row_i*column_count] = col_names[row_i-1];
+ row_major[row_i*column_count + 1] = ni[row_i-1];
+ row_major[row_i*column_count + 2] = yi_bar[row_i-1];
+ row_major[row_i*column_count + 3] = zi_bar[row_i-1];
+
+ }
+ m_stats_table = getHtmlTable(row_count, column_count, row_major);
+
+ p_value = nsl_stats_fdist_p(f_value, static_cast(np-1), df);
+
+ printLine(0, "Null Hypothesis: Variance is equal between all classes", "blue");
+ printLine(1, "Alternate Hypothesis: Variance is not equal in at-least one pair of classes", "blue");
+ printLine(2, i18n("Significance level is %1", m_significance_level), "blue");
+ printLine(4, i18n("F Value is %1 ", f_value), "green");
+ printLine(5, i18n("P Value is %1 ", p_value), "green");
+ printLine(6, i18n("Degree of Freedom is %1", df), "green");
+
+ if (p_value <= m_significance_level) {
+ q->m_view->setResultLine(5, i18n("We can safely reject Null Hypothesis for significance level %1", m_significance_level), Qt::ToolTipRole);
+ printLine(8, "Requirement for homogeneity is not met", "red");
+ } else {
+ q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole);
+ printLine(8, "Requirement for homogeneity is met", "green");
+ }
+ emit q->changed();
+ return;
+}
/***************************************Helper Functions*************************************/
HypothesisTestPrivate::ErrorType HypothesisTestPrivate::findStats(const Column* column, int &count, double &sum, double &mean, double &std) {
@@ -519,75 +761,81 @@
return HypothesisTestPrivate::NoError;
}
-HypothesisTestPrivate::ErrorType HypothesisTestPrivate::findStatsCategorical(const Column *column1, const Column *column2, int n[], double sum[], double mean[], double std[], QString &col1_name, QString &col2_name) {
- // clearing and initialising variables;
+void HypothesisTestPrivate::countPartitions(Column *column, int &np, int &total_rows) {
+ total_rows = column->rowCount();
+ np = 0;
+ QString cell_value;
+ QMap discovered_categorical_var;
- const Column* columns[] = {column1, column2};
+ AbstractColumn::ColumnMode original_col_mode = column->columnMode();
+ column->setColumnMode(AbstractColumn::Text);
- for (int i = 0; i < 2; i++) {
+ for (int i = 0; i < total_rows; i++) {
+ cell_value = column->textAt(i);
+
+ if (cell_value.isEmpty()) {
+ total_rows = i;
+ break;
+ }
+
+ if (discovered_categorical_var[cell_value])
+ continue;
+
+ discovered_categorical_var[cell_value] = true;
+ np++;
+ }
+ column->setColumnMode(original_col_mode);
+}
+
+HypothesisTestPrivate::ErrorType HypothesisTestPrivate::findStatsCategorical(Column *column1, Column *column2, int n[], double sum[], double mean[], double std[], QMap &col_name, const int &np, const int &total_rows) {
+ Column* columns[] = {column1, column2};
+ for (int i = 0; i < np; i++) {
+ n[i] = 0;
sum[i] = 0;
mean[i] = 0;
std[i] = 0;
- n[i] = 0;
}
+ AbstractColumn::ColumnMode original_col_mode = columns[0]->columnMode();
+ columns[0]->setColumnMode(AbstractColumn::Text);
- int count_temp = columns[0]->rowCount();
- col1_name = "";
- col2_name = "";
- for (int i = 0; i < count_temp; i++) {
+ int partition_number = 1;
+ for (int i = 0; i < total_rows; i++) {
QString name = columns[0]->textAt(i);
+
+ name = columns[0]->textAt(i);
double value = columns[1]->valueAt(i);
- if (name.isEmpty() || std::isnan(value)) {
- if (name.isEmpty() && std::isnan(value))
- break;
- else
- return HypothesisTestPrivate::ErrorUnqualSize;
+ if (std::isnan(value)) {
+ columns[0]->setColumnMode(original_col_mode);
+ return HypothesisTestPrivate::ErrorUnqualSize;
}
- if (name == col1_name) {
- n[0]++;
- sum[0] += value;
- } else if (name == col2_name) {
- n[1]++;
- sum[1] += value;
- } else if (col1_name.isEmpty()) {
- n[0]++;
- sum[0] += value;
- col1_name = name;
- } else if (col2_name.isEmpty()) {
- n[1]++;
- sum[1] += value;
- col2_name = name;
+ if (col_name[name] == 0) {
+ col_name[name] = partition_number;
+ partition_number++;
}
- else
- return HypothesisTestPrivate::ErrorNotTwoCategoricalVariables;
- }
-
- if (col1_name.isEmpty() || col2_name.isEmpty())
- return HypothesisTestPrivate::ErrorNotTwoCategoricalVariables;
-
- mean[0] = sum[0]/n[0];
- mean[1] = sum[1]/n[1];
+ n[col_name[name]-1]++;
+ sum[col_name[name]-1] += value;
+ }
+ for (int i = 0; i < np; i++)
+ mean[i] = sum[i] / n[i];
- for (int i = 0; i < n[0]+n[1]; i++) {
+ for (int i = 0; i < total_rows; i++) {
QString name = columns[0]->textAt(i);
double value = columns[1]->valueAt(i);
- if (name == col1_name)
- std[0] += qPow( (value - mean[0]), 2);
- else
- std[1] += qPow( (value - mean[1]), 2);
+ std[col_name[name]-1] += qPow( (value - mean[col_name[name]-1]), 2);
}
- for (int i = 0; i < 2; i++) {
+ for (int i = 0; i < np; i++) {
if (n[i] > 1)
std[i] = std[i] / (n[i] - 1);
std[i] = qSqrt(std[i]);
}
+ columns[0]->setColumnMode(original_col_mode);
return HypothesisTestPrivate::NoError;
}
diff --git a/src/backend/hypothesis_test/HypothesisTestPrivate.h b/src/backend/hypothesis_test/HypothesisTestPrivate.h
--- a/src/backend/hypothesis_test/HypothesisTestPrivate.h
+++ b/src/backend/hypothesis_test/HypothesisTestPrivate.h
@@ -40,15 +40,16 @@
virtual ~HypothesisTestPrivate();
enum TestType {TestT, TestZ};
- enum ErrorType {ErrorUnqualSize, ErrorNotTwoCategoricalVariables, ErrorEmptyColumn, NoError};
+ enum ErrorType {ErrorUnqualSize, ErrorEmptyColumn, NoError};
QString name() const;
void setDataSourceSpreadsheet(Spreadsheet* spreadsheet);
void setColumns(QStringList cols);
- void performTwoSampleIndependentTest(TestType test, bool equal_variance = true);
+ void performTwoSampleIndependentTest(TestType test, bool categorical_variable = false, bool equal_variance = true);
void performTwoSamplePairedTest(TestType test);
- void PerformOneSampleTest(TestType test);
+ void performOneSampleTest(TestType test);
+ void performLeveneTest(bool categorical_variable);
HypothesisTest* const q;
HypothesisTest::DataSourceType dataSourceType{HypothesisTest::DataSourceSpreadsheet};
@@ -65,9 +66,11 @@
QString m_stats_table;
HypothesisTest::TailType tail_type;
private:
+ void countPartitions(Column* column, int &np, int &total_rows);
+
ErrorType findStats(const Column* column,int &count, double &sum, double &mean, double &std);
ErrorType findStatsPaired(const Column *column1, const Column *column2, int &count, double &sum, double &mean, double &std);
- ErrorType findStatsCategorical(const Column *column1, const Column *column2, int n[2], double sum[2], double mean[2], double std[2], QString &col1_name, QString &col2_name);
+ ErrorType findStatsCategorical(Column *column1, Column *column2, int n[], double sum[], double mean[], double std[], QMap &col_name, const int &np, const int &total_rows);
double getPValue(const TestType &test, double &value, const QString &col1_name, const QString &col2_name, const int df);
QString getHtmlTable(int row, int column, QVariant *row_major);
diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.h b/src/kdefrontend/dockwidgets/HypothesisTestDock.h
--- a/src/kdefrontend/dockwidgets/HypothesisTestDock.h
+++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.h
@@ -83,8 +83,9 @@
// void nameChanged();
// void commentChanged();
void dataSourceTypeChanged(int);
- void doHypothesisTest();
void showHypothesisTest();
+ void doHypothesisTest();
+ void performLeveneTest();
void spreadsheetChanged(const QModelIndex&);
void col1CatIndexChanged(int index);
// void connectionChanged();
diff --git a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp
--- a/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp
+++ b/src/kdefrontend/dockwidgets/HypothesisTestDock.cpp
@@ -80,6 +80,8 @@
// making all test blocks invisible at starting.
ui.lCol1Categorical->setVisible(false);
ui.cbCol1Categorical->setVisible(false);
+ ui.pbLeveneTest->setVisible(false);
+ ui.chbCategorical->setVisible(false);
ui.lCol1->setVisible(false);
ui.cbCol1->setVisible(false);
ui.lCol2->setVisible(false);
@@ -187,13 +189,15 @@
// connect(ui.cbTest, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::showHypothesisTest);
// connect(ui.cbTestType, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::showHypothesisTest);
connect(ui.pbPerformTest, &QPushButton::clicked, this, &HypothesisTestDock::doHypothesisTest);
+ connect(ui.pbLeveneTest, &QPushButton::clicked, this, &HypothesisTestDock::performLeveneTest);
+
//connecting null hypothesis and alternate hypothesis radio button
connect(ui.rbH1OneTail1, &QRadioButton::toggled, this, &HypothesisTestDock::onRbH1OneTail1Toggled);
connect(ui.rbH1OneTail2, &QRadioButton::toggled, this, &HypothesisTestDock::onRbH1OneTail2Toggled);
connect(ui.rbH1TwoTail, &QRadioButton::toggled, this, &HypothesisTestDock::onRbH1TwoTailToggled);
- connect(ui.cbCol1Categorical, QOverload::of(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::col1CatIndexChanged);
+ connect(ui.cbCol1Categorical, static_cast(&QComboBox::currentIndexChanged), this, &HypothesisTestDock::col1CatIndexChanged);
}
void HypothesisTestDock::setHypothesisTest(HypothesisTest* HypothesisTest) {
@@ -268,6 +272,8 @@
ui.lCol2->setVisible(two_sample_independent || two_sample_paired || one_sample);
ui.cbCol2->setVisible(two_sample_independent || two_sample_paired || one_sample);
ui.chbEqualVariance->setVisible(ttest && two_sample_independent);
+ ui.chbCategorical->setVisible(ttest && two_sample_independent);
+ ui.pbLeveneTest->setVisible(ttest && two_sample_independent);
ui.chbEqualVariance->setChecked(true);
ui.pbPerformTest->setEnabled(two_sample_independent || two_sample_paired || one_sample);
@@ -304,7 +310,7 @@
if(two_sample_independent) {
cols << ui.cbCol1Categorical->currentText() << ui.cbCol2->currentText();
m_hypothesisTest->setColumns(cols);
- m_hypothesisTest->performTwoSampleIndependentTTest( ui.chbEqualVariance->isChecked());
+ m_hypothesisTest->performTwoSampleIndependentTTest(ui.chbCategorical->isChecked(), ui.chbEqualVariance->isChecked());
}
else if(two_sample_paired) {
cols << ui.cbCol1->currentText();
@@ -315,7 +321,7 @@
else if(one_sample){
cols << ui.cbCol1->currentText();
m_hypothesisTest->setColumns(cols);
- m_hypothesisTest->PerformOneSampleTTest();
+ m_hypothesisTest->performOneSampleTTest();
}
}
else if(ztest) {
@@ -334,11 +340,21 @@
else if(one_sample){
cols << ui.cbCol1->currentText();
m_hypothesisTest->setColumns(cols);
- m_hypothesisTest->PerformOneSampleZTest();
+ m_hypothesisTest->performOneSampleZTest();
}
}
}
+void HypothesisTestDock::performLeveneTest() {
+
+ QStringList cols;
+ cols << ui.cbCol1Categorical->currentText() << ui.cbCol2->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->setSignificanceLevel(ui.leAlpha->text());
+
+ m_hypothesisTest->performLeveneTest(ui.chbCategorical->isChecked());
+}
+
//void HypothesisTestDock::setModelIndexFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) {
// if (aspect)
// cb->setCurrentModelIndex(m_aspectTreeModel->modelIndexOfAspect(aspect));
@@ -469,7 +485,7 @@
//}
void HypothesisTestDock::dataSourceTypeChanged(int index) {
- HypothesisTest::DataSourceType type = (HypothesisTest::DataSourceType)index;
+ HypothesisTest::DataSourceType type = static_cast(index);
bool showDatabase = (type == HypothesisTest::DataSourceDatabase);
ui.lSpreadsheet->setVisible(!showDatabase);
cbSpreadsheet->setVisible(!showDatabase);
@@ -519,9 +535,13 @@
if (col1->columnMode() == AbstractColumn::Integer || col1->columnMode() == AbstractColumn::Numeric) {
ui.lCol2->setText( i18n("Independent Variable"));
+ ui.chbCategorical->setChecked(false);
+ ui.chbCategorical->setEnabled(true);
}
else {
ui.lCol2->setText( i18n("Dependent Variable"));
+ ui.chbCategorical->setChecked(true);
+ ui.chbCategorical->setEnabled(false);
}
}
diff --git a/src/kdefrontend/hypothesis_test/HypothesisTestView.h b/src/kdefrontend/hypothesis_test/HypothesisTestView.h
--- a/src/kdefrontend/hypothesis_test/HypothesisTestView.h
+++ b/src/kdefrontend/hypothesis_test/HypothesisTestView.h
@@ -49,7 +49,6 @@
class QItemSelection;
class QLabel;
class QTextEdit;
-class QLineEdit;
class HypothesisTestView : public QWidget {
Q_OBJECT
@@ -75,7 +74,7 @@
HypothesisTest* m_hypothesisTest;
QLabel* m_testName;
- QLabel* m_statsTable;
+ QTextEdit* m_statsTable;
QWidget* m_summaryResults;
QLabel* m_resultLine[10];
diff --git a/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp b/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp
--- a/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp
+++ b/src/kdefrontend/hypothesis_test/HypothesisTestView.cpp
@@ -41,6 +41,7 @@
#include
#include
#include
+#include
#include
#include
@@ -59,10 +60,11 @@
HypothesisTestView::HypothesisTestView(HypothesisTest* hypothesisTest) : QWidget(),
m_hypothesisTest(hypothesisTest),
m_testName(new QLabel()),
- m_statsTable(new QLabel()),
+ m_statsTable(new QTextEdit()),
m_summaryResults(new QWidget()){
- m_summaryResults->setMouseTracking(true);
+ m_statsTable->setReadOnly(true);
+
auto* layout = new QVBoxLayout(this);
layout->addWidget(m_testName);
layout->addWidget(m_statsTable);
@@ -166,7 +168,7 @@
void HypothesisTestView::changed() {
m_testName->setText(m_hypothesisTest->testName());
- m_statsTable->setText(m_hypothesisTest->statsTable());
+ m_statsTable->setHtml(m_hypothesisTest->statsTable());
}
void HypothesisTestView::exportToFile(const QString& path, const bool exportHeader, const QString& separator, QLocale::Language language) const {
diff --git a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui
--- a/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui
+++ b/src/kdefrontend/ui/dockwidgets/hypothesistestdock.ui
@@ -36,7 +36,7 @@
280
- 710
+ 740
77
23
@@ -49,7 +49,7 @@
10
- 480
+ 510
341
106
@@ -126,7 +126,7 @@
10
- 610
+ 640
217
81
@@ -304,8 +304,8 @@
- 12
- 433
+ 20
+ 460
125
23
@@ -404,6 +404,32 @@
Qt::Vertical
+
+
+
+ 20
+ 430
+ 158
+ 25
+
+
+
+ Categorical Variable
+
+
+
+
+
+ 270
+ 430
+ 121
+ 25
+
+
+
+ Levene's Test
+
+