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
@@ -36,9 +36,9 @@
class HypothesisTestPrivate;
class HypothesisTestView;
class Spreadsheet;
-class QAbstractItemModel;
class QString;
class Column;
+class QLayout;
class HypothesisTest : public AbstractPart {
Q_OBJECT
@@ -48,17 +48,29 @@
~HypothesisTest() override;
enum DataSourceType {DataSourceSpreadsheet, DataSourceDatabase};
+ enum TailType {TailPositive, TailNegative, TailTwo};
- QAbstractItemModel* dataModel();
- QAbstractItemModel *horizontalHeaderModel();
- QString testName();
+ void setDataSourceType(DataSourceType type);
+ DataSourceType dataSourceType() const;
void setDataSourceSpreadsheet(Spreadsheet* spreadsheet);
+
void setColumns(QVector cols);
void setColumns(QStringList cols);
- void performTwoSampleTTest();
- DataSourceType dataSourceType() const;
-
+ QStringList allColumns();
+ void setTailType(TailType tailType);
+ TailType tailType();
+ void setPopulationMean(QVariant populationMean);
+ void setSignificanceLevel(QVariant alpha);
+ QString testName();
+ QString statsTable();
+ void performTwoSampleTTest();
+ void performTwoSampleIndependentTTest(bool equal_variance);
+ void performTwoSamplePairedTTest();
+ void PerformOneSampleTTest();
+ void performTwoSampleIndependentZTest();
+ void performTwoSamplePairedZTest();
+ void PerformOneSampleZTest();
//virtual methods
// QIcon icon() const override;
QMenu* createContextMenu() override;
@@ -72,10 +84,6 @@
bool load(XmlStreamReader*, bool preview) override;
Spreadsheet* dataSourceSpreadsheet() const;
-
- void setDataSourceType(DataSourceType type);
- QStringList allColumns();
-
private:
HypothesisTestPrivate* const d;
mutable HypothesisTestView* m_view{nullptr};
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
@@ -44,39 +44,32 @@
#include
#include
#include
+#include
+#include
HypothesisTest::HypothesisTest(const QString &name) : AbstractPart(name),
-d(new HypothesisTestPrivate(this)) {
+ d(new HypothesisTestPrivate(this)) {
}
HypothesisTest::~HypothesisTest() {
delete d;
}
-QAbstractItemModel* HypothesisTest::dataModel() {
- return d->dataModel;
-}
-
-QAbstractItemModel* HypothesisTest::horizontalHeaderModel() {
- return d->horizontalHeaderModel;
-}
-
void HypothesisTest::setDataSourceType(DataSourceType type) {
if (type != d->dataSourceType) {
d->dataSourceType = type;
}
}
+HypothesisTest::DataSourceType HypothesisTest::dataSourceType() const {
+ return d->dataSourceType;
+}
+
void HypothesisTest::setDataSourceSpreadsheet(Spreadsheet *spreadsheet) {
if (spreadsheet != d->dataSourceSpreadsheet)
d->setDataSourceSpreadsheet(spreadsheet);
}
-QStringList HypothesisTest::allColumns()
-{
- return d->all_columns;
-}
-
void HypothesisTest::setColumns(QVector cols) {
d->m_columns = cols;
}
@@ -85,25 +78,73 @@
return d->setColumns(cols);
}
-HypothesisTest::DataSourceType HypothesisTest::dataSourceType() const {
- return d->dataSourceType;
+QStringList HypothesisTest::allColumns() {
+ return d->all_columns;
}
-void HypothesisTest::performTwoSampleTTest() {
- d->performTwoSampleTTest();
+void HypothesisTest::setTailType(HypothesisTest::TailType tailType) {
+ d->tail_type = tailType;
}
+HypothesisTest::TailType HypothesisTest::tailType() {
+ return d->tail_type;
+}
+
+void HypothesisTest::setPopulationMean(QVariant populationMean) {
+ d->m_population_mean = populationMean.toDouble();
+}
+
+void HypothesisTest::setSignificanceLevel(QVariant alpha) {
+ d->m_significance_level = alpha.toDouble();
+}
+
+
QString HypothesisTest::testName() {
return d->m_currTestName;
}
+QString HypothesisTest::statsTable() {
+ return d->m_stats_table;
+}
+
+void HypothesisTest::performTwoSampleIndependentTTest(bool equal_variance) {
+ d->m_currTestName = "Two Sample Independent T Test
";
+ d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestT, equal_variance);
+}
+
+void HypothesisTest::performTwoSamplePairedTTest() {
+ d->m_currTestName = "Two Sample Paried T Test
";
+ d->performTwoSamplePairedTest(HypothesisTestPrivate::TestT);
+}
+
+void HypothesisTest::PerformOneSampleTTest() {
+ d->m_currTestName = "One Sample T Test
";
+ d->PerformOneSampleTest(HypothesisTestPrivate::TestT);
+}
+
+void HypothesisTest::performTwoSampleIndependentZTest() {
+ d->m_currTestName = "Two Sample Independent Z Test
";
+ d->performTwoSampleIndependentTest(HypothesisTestPrivate::TestZ);
+}
+
+void HypothesisTest::performTwoSamplePairedZTest() {
+ d->m_currTestName = "Two Sample Paired Z Test
";
+ d->performTwoSamplePairedTest(HypothesisTestPrivate::TestZ);
+}
+
+void HypothesisTest::PerformOneSampleZTest() {
+ d->m_currTestName = "One Sample Z Test
";
+ d->PerformOneSampleTest(HypothesisTestPrivate::TestZ);
+}
+
+
+
+
/******************************************************************************
* Private Implementations
* ****************************************************************************/
-HypothesisTestPrivate::HypothesisTestPrivate(HypothesisTest* owner) : q(owner) ,
- dataModel(new QStandardItemModel) ,
- horizontalHeaderModel(new QStandardItemModel) {
+HypothesisTestPrivate::HypothesisTestPrivate(HypothesisTest* owner) : q(owner) {
}
HypothesisTestPrivate::~HypothesisTestPrivate() {
@@ -126,103 +167,284 @@
m_columns.clear();
Column* column = new Column("column");
for (QString col : cols) {
- if (col != "") {
+ if (!cols.isEmpty()) {
column = dataSourceSpreadsheet->column(col);
-// qDebug() << "col is " << col;
m_columns.append(column);
}
}
}
-void HypothesisTestPrivate::performTwoSampleTTest() {
- dataModel->clear();
- horizontalHeaderModel->clear();
- m_currTestName = i18n("Independent Two Sample T Test");
- DEBUG("performing two sample test :DEBUG MACRO");
- qDebug() << "performing two sample test: qDebug()";
+/**************************Two Sample Independent *************************************/
+
+void HypothesisTestPrivate::performTwoSampleIndependentTest(TestType test, bool equal_variance) {
+ QString test_name;
+
+ double value;
+ int df = 0;
+ double p_value = 0;
+ clearGlobalVariables();
- QMessageBox* msg_box = new QMessageBox();
- // checking for cols;
if (m_columns.size() != 2) {
- msg_box->setText(i18n("Inappropriate number of columns selected"));
- msg_box->exec();
+ printError("Inappropriate number of columns selected");
+ emit q->changed();
+ return;
+ }
+
+ int n[2];
+ double sum[2], mean[2], std[2];
+
+ 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) {
+ for (int i = 0; i < 2; i++) {
+ findStats(m_columns[i], n[i], sum[i], mean[i], std[i]);
+
+ if (n[i] < 1) {
+ printError("At least one of selected column is empty");
+ emit q->changed();
+ return;
+ }
+ }
+ } else {
+ ErrorType error_code = findStatsCategorical(m_columns[0], m_columns[1], n, sum, mean, std, col1_name, col2_name);
+ 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: {
+ printError("At least one of selected column is empty");
+ emit q->changed();
+ return;
+ } case NoError:
+ break;
+ }
+ }
+
+ QVariant row_major[] = {"", "N", "Sum", "Mean", "Std",
+ col1_name, n[0], sum[0], mean[0], std[0],
+ col2_name, n[1], sum[1], mean[1], std[1]};
+
+ m_stats_table = getHtmlTable(3, 5, row_major);
+
+ switch (test) {
+ case TestT: {
+ test_name = "T";
+
+ if (equal_variance) {
+ df = n[0] + n[1] - 2;
+ double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df);
+ value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1]));
+ printLine(9, "Assumption: Equal Variance b/w both population means");
+ } else {
+ double temp_val;
+ temp_val = qPow( qPow(std[0], 2)/n[0] + qPow(std[1], 2)/n[1], 2);
+ temp_val = temp_val / ( (qPow( (qPow(std[0], 2)/n[0]), 2)/(n[0]-1)) + (qPow( (qPow(std[1], 2)/n[1]), 2)/(n[1]-1)));
+ df = qRound(temp_val);
+
+ value = (mean[0] - mean[1]) / (qSqrt( (qPow(std[0], 2)/n[0]) + (qPow(std[1], 2)/n[1])));
+ printLine(9, "Assumption: UnEqual Variance b/w both population means");
+ }
+ break;
+ } case TestZ: {
+ test_name = "Z";
+ df = n[0] + n[1] - 2;
+
+ double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df);
+ value = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1]));
+ }
+ }
+
+ m_currTestName = i18n("Two Sample Independent %1 Test for %2 vs %3
", test_name, col1_name, col2_name);
+ p_value = getPValue(test, value, col1_name, col2_name, df);
+
+ printLine(2, i18n("Significance level is %1", m_significance_level), "blue");
+ printLine(4, i18n("%1 Value is %2 ", test_name, 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);
+ else
+ q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole);
+
+ emit q->changed();
+ return;
+}
+
+/********************************Two Sample Paired ***************************************/
+
+void HypothesisTestPrivate::performTwoSamplePairedTest(TestType test) {
+ QString test_name;
+ int n;
+ double sum, mean, std;
+ double value;
+ int df = 0;
+ double p_value = 0;
+ clearGlobalVariables();
+
+ if (m_columns.size() != 2) {
+ printError("Inappropriate number of columns selected");
+ emit q->changed();
return;
}
- bool modeOk = true;
- bool allColumnsValid = true;
for (int i = 0; i < 2; i++) {
- if(m_columns[i]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer)
- continue;
- modeOk = false;
+ if (!(m_columns[i]->columnMode() == AbstractColumn::Numeric || m_columns[i]->columnMode() == AbstractColumn::Integer)) {
+ printError("select only columns with numbers");
+ emit q->changed();
+ return;
+ }
}
- if(!allColumnsValid) {
- msg_box->setText(i18n("one of the selected columns is invalid"));
- msg_box->exec();
+ ErrorType error_code = findStatsPaired(m_columns[0], m_columns[1], n, sum, mean, std);
+
+ switch (error_code) {
+ case ErrorUnqualSize: {
+ printError("both columns are having different sizes");
+ emit q->changed();
+ return;
+ } case ErrorEmptyColumn: {
+ printError("columns are empty");
+ emit q->changed();
+ return;
+ } case NoError:
+ break;
+ default:
+ emit q->changed();
+ return;
+ }
+
+ if (n == -1) {
+ printError("both columns are having different sizes");
+ emit q->changed();
return;
}
- if (!modeOk) {
- msg_box->setText(i18n("select only columns with numbers"));
- msg_box->exec();
+ if (n < 1) {
+ printError("columns are empty");
+ emit q->changed();
return;
}
- dataModel->setRowCount(1);
- dataModel->setColumnCount(3);
+ QVariant row_major[] = {"", "N", "Sum", "Mean", "Std",
+ "difference", n, sum, mean, std};
+
+ m_stats_table = getHtmlTable(2, 5, row_major);
+
+ switch (test) {
+ case TestT: {
+ value = mean / (std/qSqrt(n));
+ df = n - 1;
+ test_name = "T";
+ printLine(6, i18n("Degree of Freedom is %1
name(), i18n("%1",m_population_mean), df);
+ m_currTestName = i18n("One Sample %1 Test for %2 vs %3
", test_name, m_columns[0]->name(), m_columns[1]->name());
+
+ printLine(2, i18n("Significance level is %1 ", m_significance_level), "blue");
+ printLine(4, i18n("%1 Value is %2 ", test_name, value), "green");
+ printLine(5, i18n("P Value is %1 ", p_value), "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);
+ else
+ q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole);
- horizontalHeaderModel->setColumnCount(3);
+ emit q->changed();
+ return;
- int n[2];
- double sum[2], mean[2], std[2];
+}
- for (int i = 0; i < 2; i++) {
- findStats(m_columns[i], n[i], sum[i], mean[i], std[i]);
- DEBUG( "for " << i);
- DEBUG( "n is " << n[i]);
- DEBUG( "mean is " << mean[i]);
- DEBUG( "std is " << std[i]);
-
- if (n[i] < 1) {
- msg_box->setText(i18n("atleast one of selected column is empty"));
- msg_box->exec();
- return;
- }
+/******************************** One Sample ***************************************/
+
+void HypothesisTestPrivate::PerformOneSampleTest(TestType test) {
+ QString test_name;
+ double value;
+ int df = 0;
+ double p_value = 0;
+ clearGlobalVariables();
+
+ if (m_columns.size() != 1) {
+ printError("Inappropriate number of columns selected");
+ emit q->changed();
+ return;
+ }
+
+ if ( !(m_columns[0]->columnMode() == AbstractColumn::Numeric || m_columns[0]->columnMode() == AbstractColumn::Integer)) {
+ printError("select only columns with numbers");
+ emit q->changed();
+ return;
}
- int df = n[0] + n[1] - 2;
- //Assuming equal variance
- double sp = qSqrt( ((n[0]-1)*qPow(std[0],2) + (n[1]-1)*qPow(std[1],2))/df);
+ int n;
+ double sum, mean, std;
+ ErrorType error_code = findStats(m_columns[0], n, sum, mean, std);
- QDEBUG("sp is " << sp);
+ switch (error_code) {
+ case ErrorUnqualSize: {
+ printError("column is empty");
+ emit q->changed();
+ return;
+ } case NoError:
+ break;
+ default: {
+ emit q->changed();
+ return;
+ }
+ }
- double t = (mean[0] - mean[1])/(sp*qSqrt(1.0/n[0] + 1.0/n[1]));
+ QVariant row_major[] = {"", "N", "Sum", "Mean", "Std",
+ m_columns[0]->name(), n, sum, mean, std};
- // now finding p value from t value
- double p_value = nsl_stats_tdist_p(t, df);
+ m_stats_table = getHtmlTable(2, 5, row_major);
-// QString text = i18n("T value for test is %1 and\n p value is %2",t, p_value);
-// msg_box->setText(text);
-// msg_box->exec();
+ switch (test) {
+ case TestT: {
+ test_name = "T";
+ value = (mean - m_population_mean) / (std/qSqrt(n));
+ df = n - 1;
+ printLine(6, i18n("Degree of Freedom is %1", df), "blue");
+ break;
+ } case TestZ: {
+ test_name = "Z";
+ df = 0;
+ value = (mean - m_population_mean) / (std/qSqrt(n));
+ }}
- //setting dataModel
- dataModel->setItem(0, 0, new QStandardItem(QString::number(t)));
- dataModel->setItem(0, 1, new QStandardItem(QString::number(df)));
- dataModel->setItem(0, 2, new QStandardItem(QString::number(p_value)));
+ p_value = getPValue(test, value, m_columns[0]->name(), i18n("%1",m_population_mean), df);
+ m_currTestName = i18n("One Sample %1 Test for %2
", test_name, m_columns[0]->name());
+ printLine(2, i18n("Significance level is %1", m_significance_level), "blue");
+ printLine(4, i18n("%1 Value is %2", test_name, value), "green");
+ printLine(5, i18n("P Value is %1", p_value), "green");
- //setting horizontal header model
- horizontalHeaderModel->setHeaderData(0, Qt::Horizontal, "t value");
- horizontalHeaderModel->setHeaderData(1, Qt::Horizontal, "dof");
- horizontalHeaderModel->setHeaderData(2, Qt::Horizontal, "p value");
+ 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);
+ else
+ q->m_view->setResultLine(5, i18n("There is a plausibility for Null Hypothesis to be true"), Qt::ToolTipRole);
emit q->changed();
return;
+
}
-void HypothesisTestPrivate::findStats(Column* column, int &count, double &sum, double &mean, double &std) {
+/***************************************Helper Functions*************************************/
+
+HypothesisTestPrivate::ErrorType HypothesisTestPrivate::findStats(const Column* column, int &count, double &sum, double &mean, double &std) {
sum = 0;
mean = 0;
std = 0;
@@ -237,7 +459,7 @@
sum += row;
}
- if (count < 1) return;
+ if (count < 1) return HypothesisTestPrivate::ErrorEmptyColumn;
mean = sum/count;
for (int i = 0; i < count; i++) {
@@ -248,9 +470,253 @@
if (count > 1)
std = std / (count-1);
std = qSqrt(std);
+
+ return HypothesisTestPrivate::NoError;
+}
+
+HypothesisTestPrivate::ErrorType HypothesisTestPrivate::findStatsPaired(const Column* column1, const Column* column2, int &count, double &sum, double &mean, double &std) {
+ sum = 0;
+ mean = 0;
+ std = 0;
+
+ int count1 = column1->rowCount();
+ int count2 = column2->rowCount();
+
+ count = qMin(count1, count2);
+ double cell1, cell2;
+ for (int i = 0; i < count; i++) {
+ cell1 = column1->valueAt(i);
+ cell2 = column2->valueAt(i);
+
+ if (std::isnan(cell1) || std::isnan(cell2)) {
+ if (std::isnan(cell1) && std::isnan(cell2))
+ count = i;
+ else
+ return HypothesisTestPrivate::ErrorUnqualSize;
+ break;
+ }
+
+ sum += cell1 - cell2;
+ }
+
+ if (count < 1)
+ return HypothesisTestPrivate::ErrorEmptyColumn;
+
+ mean = sum/count;
+
+ double row;
+ for (int i = 0; i < count; i++) {
+ cell1 = column1->valueAt(i);
+ cell2 = column2->valueAt(i);
+ row = cell1 - cell2;
+ std += qPow( (row - mean), 2);
+ }
+
+ if (count > 1)
+ std = std / (count-1);
+
+ std = qSqrt(std);
+ 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;
+
+ const Column* columns[] = {column1, column2};
+
+ for (int i = 0; i < 2; i++) {
+ sum[i] = 0;
+ mean[i] = 0;
+ std[i] = 0;
+ n[i] = 0;
+ }
+
+ int count_temp = columns[0]->rowCount();
+ col1_name = "";
+ col2_name = "";
+ for (int i = 0; i < count_temp; i++) {
+ QString 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 (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;
+ }
+ 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];
+
+
+ for (int i = 0; i < n[0]+n[1]; 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);
+ }
+
+ for (int i = 0; i < 2; i++) {
+ if (n[i] > 1)
+ std[i] = std[i] / (n[i] - 1);
+ std[i] = qSqrt(std[i]);
+ }
+
+ return HypothesisTestPrivate::NoError;
+}
+
+
+double HypothesisTestPrivate::getPValue(const HypothesisTestPrivate::TestType &test, double &value, const QString &col1_name, const QString &col2_name, const int df) {
+ double p_value = 0;
+
+ //TODO change ("⋖") symbol to ("<"), currently macro UTF8_QSTRING is not working properly if used "<" symbol;
+ switch (test) {
+ case TestT: {
+ switch (tail_type) {
+ case HypothesisTest::TailNegative:
+ p_value = nsl_stats_tdist_p(value, df);
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("≥"), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("⋖"), col2_name), "blue");
+ break;
+ case HypothesisTest::TailPositive:
+ value *= -1;
+ p_value = nsl_stats_tdist_p(value, df);
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("≤"), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING(">"), col2_name), "blue");
+ break;
+ case HypothesisTest::TailTwo:
+ p_value = nsl_stats_tdist_p(value, df) + nsl_stats_tdist_p(-1*value, df);
+
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("="), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3", col1_name, UTF8_QSTRING("≠"), col2_name), "blue");
+ break;
+ }
+ break;
+ } case TestZ: {
+ switch (tail_type) {
+ case HypothesisTest::TailNegative:
+ p_value = nsl_stats_tdist_p(value, df);
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING("≥"), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING("⋖"), col2_name), "blue");
+ break;
+ case HypothesisTest::TailPositive:
+ value *= -1;
+ p_value = nsl_stats_tdist_p(value, df);
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING("≤"), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING(">"), col2_name), "blue");
+ break;
+ case HypothesisTest::TailTwo:
+ p_value = nsl_stats_tdist_p(value, df) + nsl_stats_tdist_p(-1*value, df);
+
+ printLine(0, i18n("Null Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING("="), col2_name), "blue");
+ printLine(1, i18n("Alternate Hypothesis: Population mean of %1 %2 Population mean of %3 ", col1_name, UTF8_QSTRING("≠"), col2_name), "blue");
+ break;
+ }
+ break;
+ }
+ }
+
+ if (p_value > 1)
+ return 1;
+ return p_value;
+}
+
+QString HypothesisTestPrivate::getHtmlTable(int row, int column, QVariant *row_major) {
+ if (row < 1 || column < 1)
+ return QString();
+
+ QString table = "";
+ table = ""
+ ""
+ " ";
+
+ QString bg = "tg-0pky";
+ bool pky = true;
+
+ QString element;
+ table += "
";
+ for (int j = 0; j < column; j++) {
+ element = row_major[j].toString();
+ table += i18n(" %2 | ", bg, element);
+ }
+ table += "
";
+
+ if (pky)
+ bg = "tg-0pky";
+ else
+ bg = "tg-btxf";
+ pky = !pky;
+
+ for (int i = 1; i < row; i++) {
+ table += " ";
+
+ QString element = row_major[i*column].toString();
+ table += i18n(" %2 | ", bg, element);
+ for (int j = 1; j < column; j++) {
+ QString element = row_major[i*column+j].toString();
+ table += i18n(" %2 | ", bg, element);
+ }
+
+ table += "
";
+ if (pky)
+ bg = "tg-0pky";
+ else
+ bg = "tg-btxf";
+ pky = !pky;
+ }
+ table += "
";
+
+ return table;
+}
+
+
+void HypothesisTestPrivate::printLine(const int &index, const QString &msg, const QString &color) {
+ q->m_view->setResultLine(index, i18n("%2
", color, msg));
return;
}
+void HypothesisTestPrivate::printError(const QString &error_msg) {
+ printLine(0, error_msg, "red");
+ emit q->changed();
+}
+
+
+void HypothesisTestPrivate::clearGlobalVariables() {
+ m_stats_table = "";
+ q->m_view->clearResult();
+}
/**********************************************************************************
* virtual functions implementations
@@ -315,7 +781,7 @@
*/
QMenu* HypothesisTest::createContextMenu() {
QMenu* menu = AbstractPart::createContextMenu();
-// Q_ASSERT(menu);
-// emit requestProjectContextMenu(menu);
+ // Q_ASSERT(menu);
+ // emit requestProjectContextMenu(menu);
return menu;
}
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
@@ -35,34 +35,47 @@
class HypothesisTestPrivate {
public:
+
explicit HypothesisTestPrivate(HypothesisTest*);
virtual ~HypothesisTestPrivate();
+ enum TestType {TestT, TestZ};
+ enum ErrorType {ErrorUnqualSize, ErrorNotTwoCategoricalVariables, ErrorEmptyColumn, NoError};
+
QString name() const;
+ void setDataSourceSpreadsheet(Spreadsheet* spreadsheet);
+ void setColumns(QStringList cols);
+ void performTwoSampleIndependentTest(TestType test, bool equal_variance = true);
+ void performTwoSamplePairedTest(TestType test);
+ void PerformOneSampleTest(TestType test);
- HypothesisTest* const q;
+ HypothesisTest* const q;
HypothesisTest::DataSourceType dataSourceType{HypothesisTest::DataSourceSpreadsheet};
Spreadsheet* dataSourceSpreadsheet{nullptr};
-
- void setDataSourceSpreadsheet(Spreadsheet* spreadsheet);
- void setColumns(QStringList cols);
QVector m_columns;
-
QStringList all_columns;
- QStandardItemModel* dataModel{nullptr};
- QStandardItemModel* horizontalHeaderModel{nullptr};
-
bool m_dbCreated{false};
int m_rowCount{0};
int m_columnCount{0};
QString m_currTestName{"Result Table"};
-
- void performTwoSampleTTest();
+ double m_population_mean;
+ double m_significance_level;
+ QString m_stats_table;
+ HypothesisTest::TailType tail_type;
private:
- void findStats(Column* column, int &count, double &sum, double &mean, double &std);
-// QMap m_members;
+ 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);
+
+ 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);
+
+ void printLine(const int &index, const QString &msg, const QString &color = "black");
+ void printError(const QString &error_msg);
+ void clearGlobalVariables();
+
};
#endif
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
@@ -38,6 +38,7 @@
class HypothesisTest;
class TreeViewComboBox;
class KConfig;
+class QScrollArea;
class HypothesisTestDock : public QWidget {
Q_OBJECT
@@ -46,6 +47,11 @@
explicit HypothesisTestDock(QWidget*);
void setHypothesisTest(HypothesisTest*);
+private slots:
+ void onRbH1OneTail1Toggled(bool checked);
+ void onRbH1OneTail2Toggled(bool checked);
+ void onRbH1TwoTailToggled(bool checked);
+
private slots:
private:
@@ -56,21 +62,31 @@
//// AspectTreeModel* m_aspectTreeModel{nullptr};
QSqlDatabase m_db;
QString m_configPath;
-
+ double population_mean{0};
+ double significance_level{0.05};
// void load();
// void loadConfig(KConfig&);
// void setModelIndexFromAspect(TreeViewComboBox*, const AbstractAspect*);
// void readConnections();
// void updateFields();
// bool fieldSelected(const QString&);
+ bool ttest{false};
+ bool ztest{false};
+ bool two_sample_independent{false};
+ bool two_sample_paired{false};
+ bool one_sample{false};
+ QScrollArea* scroll_dock;
+
private slots:
//SLOTs for changes triggered in PivotTableDock
// void nameChanged();
// void commentChanged();
void dataSourceTypeChanged(int);
- void doTTest();
+ void doHypothesisTest();
+ void showHypothesisTest();
void spreadsheetChanged(const QModelIndex&);
+ void col1CatIndexChanged(int index);
// void connectionChanged();
// void tableChanged();
// void showDatabaseManager();
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
@@ -39,6 +39,7 @@
#include
#include
+#include
#include
#include
@@ -50,6 +51,8 @@
\ingroup kdefrontend
*/
+//TOOD: Make this dock widget scrollable and automatic resizeable for different screens.
+
HypothesisTestDock::HypothesisTestDock(QWidget* parent) : QWidget(parent) {
ui.setupUi(this);
@@ -57,12 +60,74 @@
ui.cbDataSourceType->addItem(i18n("Database"));
cbSpreadsheet = new TreeViewComboBox;
- ui.gridLayout->addWidget(cbSpreadsheet, 5, 3, 1, 4);
+ ui.gridLayout->addWidget(cbSpreadsheet, 1, 1);
ui.bDatabaseManager->setIcon(QIcon::fromTheme("network-server-database"));
ui.bDatabaseManager->setToolTip(i18n("Manage connections"));
m_configPath = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation).constFirst() + "sql_connections";
-// readConnections();
+
+
+
+
+ // adding item to tests and testtype combo box;
+ ui.cbTest->addItem(i18n("T Test"));
+ ui.cbTest->addItem(i18n("Z Test"));
+
+ ui.cbTestType->addItem(i18n("Two Sample Independent"));
+ ui.cbTestType->addItem(i18n("Two Sample Paired"));
+ ui.cbTestType->addItem(i18n("One Sample"));
+
+ // making all test blocks invisible at starting.
+ ui.lCol1Categorical->setVisible(false);
+ ui.cbCol1Categorical->setVisible(false);
+ ui.lCol1->setVisible(false);
+ ui.cbCol1->setVisible(false);
+ ui.lCol2->setVisible(false);
+ ui.cbCol2->setVisible(false);
+ ui.chbEqualVariance->setVisible(false);
+ ui.chbEqualVariance->setChecked(true);
+ ui.pbPerformTest->setEnabled(false);
+ ui.rbH1OneTail2->setVisible(false);
+ ui.rbH1OneTail1->setVisible(false);
+ ui.rbH1TwoTail->setVisible(false);
+ ui.rbH0OneTail1->setVisible(false);
+ ui.rbH0OneTail2->setVisible(false);
+ ui.rbH0TwoTail->setVisible(false);
+ ui.lH0->setVisible(false);
+ ui.lH1->setVisible(false);
+
+ QString mu = UTF8_QSTRING("μ");
+ QString mu0 = UTF8_QSTRING("μₒ");
+
+ // radio button for null and alternate hypothesis
+ // for alternative hypothesis (h1)
+ // one_tail_1 is mu > mu0; one_tail_2 is mu < mu0; two_tail = mu != mu0;
+
+ ui.rbH1OneTail1->setText( i18n("%1 %2 %3", mu, UTF8_QSTRING(">"), mu0));
+ ui.rbH1OneTail2->setText( i18n("%1 %2 %3", mu, UTF8_QSTRING("<"), mu0));
+ ui.rbH1TwoTail->setText( i18n("%1 %2 %3", mu, UTF8_QSTRING("≠"), mu0));
+
+ ui.rbH0OneTail1->setText( i18n("%1 %2 %3",mu, UTF8_QSTRING("≤"), mu0));
+ ui.rbH0OneTail2->setText( i18n("%1 %2 %3", mu, UTF8_QSTRING("≥"), mu0));
+ ui.rbH0TwoTail->setText( i18n("%1 %2 %3", mu, UTF8_QSTRING("="), mu0));
+
+ ui.rbH0TwoTail->setEnabled(false);
+ ui.rbH0OneTail1->setEnabled(false);
+ ui.rbH0OneTail2->setEnabled(false);
+
+
+ // setting muo and alpha buttons
+ ui.lMuo->setText( i18n("%1", mu0));
+ ui.lAlpha->setText( i18n("%1", UTF8_QSTRING("α")));
+ ui.leMuo->setText( i18n("%1", population_mean));
+ ui.leAlpha->setText( i18n("%1", significance_level));
+
+ ui.lMuo->setVisible(false);
+ ui.lAlpha->setVisible(false);
+ ui.leMuo->setVisible(false);
+ ui.leAlpha->setVisible(false);
+
+ // readConnections();
// auto* style = ui.bAddRow->style();
// ui.bAddRow->setIcon(style->standardIcon(QStyle::SP_ArrowRight));
@@ -117,7 +182,18 @@
// ui.bRemoveColumn->setEnabled(!ui.lwColumns->selectedItems().isEmpty());
// });
- connect(ui.pbPerformTest, &QPushButton::clicked, this, &HypothesisTestDock::doTTest);
+ connect(ui.cbTest, static_cast(&QComboBox::activated), this, &HypothesisTestDock::showHypothesisTest);
+ connect(ui.cbTestType, static_cast(&QComboBox::activated), this, &HypothesisTestDock::showHypothesisTest);
+// 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);
+
+ //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);
}
void HypothesisTestDock::setHypothesisTest(HypothesisTest* HypothesisTest) {
@@ -145,13 +221,16 @@
// else
// ui.cbConnection->setCurrentIndex(ui.cbConnection->findText(m_hypothesisTest->dataSourceConnection()));
-
//clearing all cbCol*
ui.cbCol1->clear();
ui.cbCol2->clear();
+ ui.cbCol1Categorical->clear();
for (auto* col : m_hypothesisTest->dataSourceSpreadsheet()->children()) {
- ui.cbCol1->addItem(col->name());
- ui.cbCol2->addItem(col->name());
+ ui.cbCol1Categorical->addItem(col->name());
+ if (col->columnMode() == AbstractColumn::Integer || col->columnMode() == AbstractColumn::Numeric) {
+ ui.cbCol2->addItem(col->name());
+ ui.cbCol1->addItem(col->name());
+ }
}
this->dataSourceTypeChanged(ui.cbDataSourceType->currentIndex());
@@ -174,12 +253,90 @@
// m_initializing = false;
}
-void HypothesisTestDock::doTTest() {
+void HypothesisTestDock::showHypothesisTest() {
+ ttest = ui.cbTest->currentText() == "T Test";
+ ztest = ui.cbTest->currentText() == "Z Test";
+
+ two_sample_independent = ui.cbTestType->currentText() == "Two Sample Independent";
+ two_sample_paired = ui.cbTestType->currentText() == "Two Sample Paired";
+ one_sample = ui.cbTestType->currentText() == "One Sample";
+
+ ui.lCol1Categorical->setVisible(two_sample_independent);
+ ui.cbCol1Categorical->setVisible(two_sample_independent);
+ ui.lCol1->setVisible(two_sample_paired);
+ ui.cbCol1->setVisible(two_sample_paired);
+ 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.chbEqualVariance->setChecked(true);
+ ui.pbPerformTest->setEnabled(two_sample_independent || two_sample_paired || one_sample);
+
+ ui.rbH1OneTail2->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.rbH1OneTail1->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.rbH1TwoTail->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.rbH0OneTail1->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.rbH0OneTail2->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.rbH0TwoTail->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.lH0->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.lH1->setVisible(two_sample_independent || two_sample_paired || one_sample);
+
+ ui.rbH1TwoTail->setChecked(true);
+
+ ui.lMuo->setVisible(one_sample);
+ ui.leMuo->setVisible(one_sample);
+ ui.lAlpha->setVisible(two_sample_independent || two_sample_paired || one_sample);
+ ui.leAlpha->setVisible(two_sample_independent || two_sample_paired || one_sample);
+
+ ui.leMuo->setText( i18n("%1", population_mean));
+ ui.leAlpha->setText( i18n("%1", significance_level));
+
+ if (two_sample_independent)
+ ui.lCol2->setText( i18n("Independent Variable"));
+}
+
+void HypothesisTestDock::doHypothesisTest() {
+
+ m_hypothesisTest->setPopulationMean(ui.leMuo->text());
+ m_hypothesisTest->setSignificanceLevel(ui.leAlpha->text());
+
QStringList cols;
- cols << ui.cbCol1->currentText();
- cols << ui.cbCol2->currentText();
- m_hypothesisTest->setColumns(cols);
- m_hypothesisTest->performTwoSampleTTest();
+ if(ttest) {
+ if(two_sample_independent) {
+ cols << ui.cbCol1Categorical->currentText() << ui.cbCol2->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->performTwoSampleIndependentTTest( ui.chbEqualVariance->isChecked());
+ }
+ else if(two_sample_paired) {
+ cols << ui.cbCol1->currentText();
+ cols << ui.cbCol2->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->performTwoSamplePairedTTest();
+ }
+ else if(one_sample){
+ cols << ui.cbCol1->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->PerformOneSampleTTest();
+ }
+ }
+ else if(ztest) {
+ if(two_sample_independent) {
+ cols << ui.cbCol1Categorical->currentText();
+ cols << ui.cbCol2->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->performTwoSampleIndependentZTest();
+ }
+ else if(two_sample_paired) {
+ cols << ui.cbCol1->currentText();
+ cols << ui.cbCol2->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->performTwoSamplePairedZTest();
+ }
+ else if(one_sample){
+ cols << ui.cbCol1->currentText();
+ m_hypothesisTest->setColumns(cols);
+ m_hypothesisTest->PerformOneSampleZTest();
+ }
+ }
}
//void HypothesisTestDock::setModelIndexFromAspect(TreeViewComboBox* cb, const AbstractAspect* aspect) {
@@ -333,20 +490,42 @@
Spreadsheet* spreadsheet = dynamic_cast(aspect);
//clear the previous definitions of combo-box columns
+ //clearing all cbCol*
ui.cbCol1->clear();
ui.cbCol2->clear();
- //TODO:
- //rows, columns, values
-
- //show all spreadsheet columns as available dimensions
- for (const auto* col : spreadsheet->children()) {
- ui.cbCol1->addItem(col->name());
- ui.cbCol2->addItem(col->name());
+ ui.cbCol1Categorical->clear();
+ for (auto* col : m_hypothesisTest->dataSourceSpreadsheet()->children()) {
+ ui.cbCol1Categorical->addItem(col->name());
+ if (col->columnMode() == AbstractColumn::Integer || col->columnMode() == AbstractColumn::Numeric) {
+ ui.cbCol2->addItem(col->name());
+ ui.cbCol1->addItem(col->name());
+ }
}
m_hypothesisTest->setDataSourceSpreadsheet(spreadsheet);
}
+// currently no need of this slot
+void HypothesisTestDock::col1CatIndexChanged(int index) {
+ if (index < 0) return;
+
+ if (two_sample_paired) {
+ ui.lCol2->setText( i18n("Independent Variable"));
+ return;
+ }
+
+ QString selected_text = ui.cbCol1Categorical->currentText();
+ Column* col1 = m_hypothesisTest->dataSourceSpreadsheet()->column(selected_text);
+
+ if (col1->columnMode() == AbstractColumn::Integer || col1->columnMode() == AbstractColumn::Numeric) {
+ ui.lCol2->setText( i18n("Independent Variable"));
+ }
+ else {
+ ui.lCol2->setText( i18n("Dependent Variable"));
+ }
+
+}
+
//void HypothesisTestDock::connectionChanged() {
// if (ui.cbConnection->currentIndex() == -1) {
@@ -478,3 +657,24 @@
// Q_UNUSED(config);
//}
+//TODO: Rather than inbuilt slots use own decided slots for checked rather than clicked
+
+// for alternate hypothesis
+// one_tail_1 is mu > mu0; one_tail_2 is mu < mu0; two_tail = mu != mu0;
+void HypothesisTestDock::onRbH1OneTail1Toggled(bool checked) {
+ if (!checked) return;
+ ui.rbH0OneTail1->setChecked(true);
+ m_hypothesisTest->setTailType(HypothesisTest::TailPositive);
+}
+
+void HypothesisTestDock::onRbH1OneTail2Toggled(bool checked) {
+ if (!checked) return;
+ ui.rbH0OneTail2->setChecked(true);
+ m_hypothesisTest->setTailType(HypothesisTest::TailNegative);
+}
+
+void HypothesisTestDock::onRbH1TwoTailToggled(bool checked) {
+ if (!checked) return;
+ ui.rbH0TwoTail->setChecked(true);
+ m_hypothesisTest->setTailType(HypothesisTest::TailTwo);
+}
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
@@ -40,6 +40,7 @@
class AbstractAspect;
class QTableView;
class QHeaderView;
+class QListView;
class QPrinter;
class QMenu;
@@ -47,6 +48,8 @@
class QModelIndex;
class QItemSelection;
class QLabel;
+class QTextEdit;
+class QLineEdit;
class HypothesisTestView : public QWidget {
Q_OBJECT
@@ -70,10 +73,11 @@
const bool gridLines, const bool captions, const bool latexHeaders,
const bool skipEmptyRows,const bool exportEntire) const;
- HypothesisTest* m_hypothesisTest;
- QTableView* m_tableView;
- QHeaderView* m_horizontalHeaderView;
- QLabel* m_testName;
+ HypothesisTest* m_hypothesisTest;
+ QLabel* m_testName;
+ QLabel* m_statsTable;
+ QWidget* m_summaryResults;
+ QLabel* m_resultLine[10];
public slots:
void createContextMenu(QMenu*);
@@ -81,9 +85,9 @@
void print(QPrinter*) const;
void changed();
+ void setResultLine(int index, QVariant data, Qt::ItemDataRole role = Qt::DisplayRole);
+ void clearResult();
private slots:
- void goToCell();
- void goToCell(int row, int col);
};
#endif
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
@@ -39,9 +39,8 @@
#include
#include
#include
-#include
-#include
#include
+#include
#include
#include
@@ -59,41 +58,16 @@
HypothesisTestView::HypothesisTestView(HypothesisTest* hypothesisTest) : QWidget(),
m_hypothesisTest(hypothesisTest),
- m_tableView(new QTableView(this)),
- m_horizontalHeaderView(new QHeaderView(Qt::Horizontal, m_tableView)),
- m_testName(new QLabel()) {
-
- //setting alignments and fonts of testname label;
- m_testName->setText(m_hypothesisTest->testName());
-// m_testName->setAlignment(Qt::AlignCenter);
- QFont font = m_testName->font();
- font.setPointSize(15);
- m_testName->setFont(font);
-
- //setting properties for table view
- m_tableView->setEditTriggers(QAbstractItemView::NoEditTriggers);
-// m_tableView->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
-
-// QHBoxLayout* tableLayout = new QHBoxLayout(m_tableView);
-// m_tableView->setLayout(tableLayout);
-// m_tableView->setLayout(Qt::ho)
+ m_testName(new QLabel()),
+ m_statsTable(new QLabel()),
+ m_summaryResults(new QWidget()){
+ m_summaryResults->setMouseTracking(true);
auto* layout = new QVBoxLayout(this);
- layout->setContentsMargins(0,0,0,0);
layout->addWidget(m_testName);
- layout->addSpacing(5);
- layout->addWidget(m_tableView);
-// layout->setAlignment(m_testName, Qt::AlignHCenter);
-// layout->setAlignment(m_tableView, Qt::AlignJustify);
-
-
- m_horizontalHeaderView->setVisible(true);
- m_horizontalHeaderView->setEnabled(true);
- m_horizontalHeaderView->setSectionsClickable(true);
-
- m_tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
- m_tableView->setHorizontalHeader(m_horizontalHeaderView);
- m_tableView->verticalHeader()->setVisible(false);
+ layout->addWidget(m_statsTable);
+ layout->addWidget(m_summaryResults);
+ layout->addWidget(m_summaryResults);
init();
}
@@ -103,12 +77,19 @@
initActions();
initMenus();
- m_tableView->setModel(m_hypothesisTest->dataModel());
- m_horizontalHeaderView->setModel(m_hypothesisTest->horizontalHeaderModel());
+// m_summaryResults->setStyleSheet("background-color:white; border: 0px; margin: 0px; padding 0px;qproperty-frame: false;");
+ QVBoxLayout* summary_layout = new QVBoxLayout(m_summaryResults);
+
+ for (int i = 0; i < 10; i++) {
+ m_resultLine[i] = new QLabel();
+ summary_layout->addWidget(m_resultLine[i]);
+ }
connect(m_hypothesisTest, &HypothesisTest::changed, this, &HypothesisTestView::changed);
}
+
+
void HypothesisTestView::initActions() {
}
@@ -117,6 +98,20 @@
}
+void HypothesisTestView::setResultLine(int index, QVariant data, Qt::ItemDataRole role) {
+ if (index < 0 || index >= 10) return;
+
+ if (role == Qt::DisplayRole)
+ m_resultLine[index]->setText(data.toString());
+ else if (role == Qt::ToolTipRole)
+ m_resultLine[index]->setToolTip(data.toString());
+}
+
+void HypothesisTestView::clearResult() {
+ for (int i = 0; i < 10; i++)
+ m_resultLine[i]->clear();
+}
+
void HypothesisTestView::connectActions() {
}
@@ -136,24 +131,6 @@
Q_ASSERT(menu);
}
-void HypothesisTestView::goToCell() {
- bool ok;
-
- int col = QInputDialog::getInt(nullptr, i18n("Go to Cell"), i18n("Enter column"), 1, 1, m_tableView->model()->columnCount(), 1, &ok);
- if (!ok) return;
-
- int row = QInputDialog::getInt(nullptr, i18n("Go to Cell"), i18n("Enter row"), 1, 1, m_tableView->model()->rowCount(), 1, &ok);
- if (!ok) return;
-
- goToCell(row-1, col-1);
-}
-
-void HypothesisTestView::goToCell(int row, int col) {
- QModelIndex index = m_tableView->model()->index(row, col);
- m_tableView->scrollTo(index);
- m_tableView->setCurrentIndex(index);
-}
-
bool HypothesisTestView::exportView() {
return true;
}
@@ -189,6 +166,7 @@
void HypothesisTestView::changed() {
m_testName->setText(m_hypothesisTest->testName());
+ m_statsTable->setText(m_hypothesisTest->statsTable());
}
void HypothesisTestView::exportToFile(const QString& path, const bool exportHeader, const QString& separator, QLocale::Language language) const {
@@ -216,5 +194,5 @@
if (!file.open(QFile::WriteOnly | QFile::Truncate))
return;
- PERFTRACE("export pivot table to latex");
+ PERFTRACE("export pivot table to latex");
}
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
@@ -13,282 +13,397 @@
Form
-
- -
-
-
-
- Tests
-
-
+
+
+
+ 9
+ 255
+ 73
+ 17
+
+
+
+
+ 75
+ true
+
+
+
+ Structure:
+
+
+
+
+
+ 280
+ 710
+ 77
+ 23
+
+
+
+ Do Test
+
+
+
+
+
+ 10
+ 480
+ 341
+ 106
+
+
+
+ Qt::Horizontal
+
+
+
-
-
- T Test
-
-
-
+
+
+ Alternate Hypothesis
+
+
+
+ -
+
+
+ mu > muo
+
+
+
+ -
+
+
+ mu < muo
+
+
+
+ -
+
+
+ mu != muo
+
+
+
+
+
+
+
+ -
+
+
+ Null Hypothesis
+
+
+
+ -
+
+
+ mu <= muo
+
+
+
+ -
+
+
+ mu >= muo
+
+
+
+ -
+
- Independent Sample T-Test
+ mu == muo
-
+
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 13
-
-
-
-
- -
-
-
- Source:
-
-
-
- -
-
-
- Qt::Horizontal
-
-
- QSizePolicy::Fixed
-
-
-
- 13
- 23
-
-
-
-
- -
-
-
- Table:
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- Comment:
-
-
-
- -
-
-
- Connection:
-
-
-
- -
-
-
- Spreadsheet:
-
-
-
- -
-
-
-
- 75
- true
-
-
-
- Data
-
-
-
- -
-
-
-
- 75
- true
-
-
-
- Structure:
-
-
-
- -
-
-
- -
-
-
-
- 0
- 0
-
-
-
- Name:
-
-
-
- -
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- Column 1
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- -
-
-
- Qt::Vertical
-
-
- QSizePolicy::Fixed
-
-
-
- 20
- 20
-
-
-
-
- -
-
-
- Qt::Vertical
-
-
-
- 20
- 40
-
-
-
-
- -
-
-
- true
-
-
- Column 2
-
-
- Qt::AlignCenter
-
-
-
- -
-
-
- OK
-
-
-
-
+
+
+
+
+
+
+ 10
+ 610
+ 217
+ 81
+
+
+
+ -
+
+
+ muo
+
+
+
+ -
+
+
+ -
+
+
+ alpha
+
+
+
+ -
+
+
+
+
+
+
+
+ 15
+ 12
+ 90
+ 25
+
+
+
+
+ 0
+ 0
+
+
+
+ Name:
+
+
+
+
+
+ 15
+ 43
+ 90
+ 25
+
+
+
+ Comment:
+
+
+
+
+
+ 130
+ 43
+ 401
+ 25
+
+
+
+
+
+
+ 130
+ 12
+ 401
+ 25
+
+
+
+
+
+
+ 15
+ 93
+ 42
+ 17
+
+
+
+
+ 75
+ true
+
+
+
+ Data
+
+
+
+
+
+ 15
+ 116
+ 531
+ 112
+
+
+
+ -
+
+
+ Source:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+ Spreadsheet:
+
+
+
+ -
+
+
+ Connection:
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ Table:
+
+
+
+ -
+
+
+
+
+
+
+
+ 12
+ 433
+ 125
+ 23
+
+
+
+ Equal Variance
+
+
+
+
+
+ 13
+ 288
+ 341
+ 50
+
+
+
+ -
+
+
+ -
+
+
+ Test
+
+
+
+ -
+
+
+ Test type
+
+
+
+ -
+
+
+
+
+
+
+
+ 16
+ 373
+ 394
+ 50
+
+
+
+ -
+
+
+ Independent Variable
+
+
+ Qt::AlignCenter
+
+
+
+ -
+
+
+ Independent Variable
+
+
+
+ -
+
+
+ Variable
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
+
+
+ 570
+ 10
+ 16
+ 981
+
+
+
+ Qt::Vertical
+
+