diff --git a/statapp/calculations.py b/statapp/calculations.py index 59761d5..c55cede 100644 --- a/statapp/calculations.py +++ b/statapp/calculations.py @@ -17,6 +17,7 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see .# import numpy as np +import pandas as pd DIRECT_LINK = 0 INDIRECT_LINK = 1 @@ -43,3 +44,7 @@ def variance_analysis(data): return np.array([ [np.mean(col), np.std(col), np.min(col), np.max(col)] for col in data.T ]) + + +def correlation_analysis(data): + return pd.DataFrame(data).corr().to_numpy() diff --git a/statapp/correlation_analysis.py b/statapp/correlation_analysis.py new file mode 100644 index 0000000..c252a45 --- /dev/null +++ b/statapp/correlation_analysis.py @@ -0,0 +1,18 @@ +from PySide2.QtWidgets import QDialog, QHeaderView + +from statapp.calculations import correlation_analysis +from statapp.models.correlation_analysis_model import CorrelationAnalysisModel +from statapp.ui.ui_correlation_analysis_window import Ui_CorrelationAnalysisWindow + + +class СorrelationAnalysisWindow(QDialog): + def __init__(self, data): + super().__init__() + self.ui = Ui_CorrelationAnalysisWindow() + self.ui.setupUi(self) + + res = correlation_analysis(data) + self.model = CorrelationAnalysisModel(res.round(2)) + self.ui.tableView.setModel(self.model) + header = self.ui.tableView.horizontalHeader() + header.setSectionResizeMode(QHeaderView.ResizeMode.Stretch) diff --git a/statapp/main_window.py b/statapp/main_window.py index 9798494..e871787 100644 --- a/statapp/main_window.py +++ b/statapp/main_window.py @@ -17,12 +17,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see .# import numpy as np -from PySide2.QtCore import Slot, QLocale, QSize +from PySide2.QtCore import Slot, QSize from PySide2.QtGui import QIcon -from PySide2.QtWidgets import QMainWindow, QMessageBox, QApplication +from PySide2.QtWidgets import QMainWindow, QMessageBox, QAction from statapp.calculations import generate_x_values -from statapp.generate_factor_window import GenerateFactorWindow, INDIRECT_LINK +from statapp.generate_factor_window import GenerateFactorWindow from statapp.models.input_values_model import InputValuesModel from statapp.generate_window import GenerateWindow from statapp.about_window import AboutWindow @@ -30,6 +30,7 @@ from statapp.models.fileslc_model import FileSLCModel from statapp.ui.ui_main_window import Ui_MainWindow from statapp.utils import resource_path, buildMessageBox from statapp.variance_analysis import VarianceAnalysisWindow +from statapp.correlation_analysis import СorrelationAnalysisWindow class MainWindow(QMainWindow): @@ -41,7 +42,10 @@ class MainWindow(QMainWindow): icon = QIcon() icon.addFile(resource_path("ui/images/logo.ico"), QSize(), QIcon.Normal, QIcon.Off) - self.setWindowIcon(icon) + + self.ui.generateXaction.setEnabled(False) + self.ui.varianceAnalysisAction.setEnabled(False) + self.ui.correlationAnalisisAction.setEnabled(False) self.isDataChanged = False self.model = InputValuesModel() @@ -51,10 +55,11 @@ class MainWindow(QMainWindow): @Slot() def on_openfileaction_triggered(self): current_data = self.model.getData() + data = np.array([]) if current_data.size > 1: file = '' if self.fileModel.file_name: - file = '\nФайл сохранения:' + self.fileModel.file_name + file = '\nФайл сохранения: ' + self.fileModel.file_name msgBox = buildMessageBox \ ('Сохранение данных', @@ -70,14 +75,27 @@ class MainWindow(QMainWindow): return else: data = self.fileModel.loadFile() - if data is not None: + if data is not None and data.shape[0] > 0: self.model.updateAllData(data) - self.isDataChanged = True + self.isDataChanged = False else: data = self.fileModel.loadFile() - if data is not None: + if data is not None and data.shape[0] > 0: self.model.updateAllData(data) - self.isDataChanged = True + self.isDataChanged = False + + if data.shape[1] == 1: + self.ui.generateXaction.setEnabled(True) + self.ui.varianceAnalysisAction.setEnabled(False) + self.ui.correlationAnalisisAction.setEnabled(False) + elif data.shape[1] > 1: + self.ui.generateXaction.setEnabled(True) + self.ui.varianceAnalysisAction.setEnabled(True) + self.ui.correlationAnalisisAction.setEnabled(True) + else: + self.ui.generateXaction.setEnabled(False) + self.ui.varianceAnalysisAction.setEnabled(False) + self.ui.correlationAnalisisAction.setEnabled(False) @Slot() def on_savefileaction_triggered(self): @@ -95,6 +113,7 @@ class MainWindow(QMainWindow): y = np.random.normal(gw.mat, gw.deviation, size=(gw.count, 1)) self.model.updateAllData(y.round(2)) self.isDataChanged = True + self.generateXaction_action.setEnabled(True) @Slot() def on_generateXaction_triggered(self): @@ -108,12 +127,19 @@ class MainWindow(QMainWindow): # dd = dd.reshape(len(dd), 1) data = np.concatenate((data, x_arr), axis=1) self.model.updateAllData(data) + self.varianceAnalysisAction_action.setEnabled(True) + self.correlationAnalisisAction_action.setEnabled(True) self.isDataChanged = True @Slot() def on_aboutmenuaction_triggered(self): global about_window about_window = AboutWindow() + + icon = QIcon() + icon.addFile(resource_path("ui/images/logo.ico"), QSize(), QIcon.Normal, QIcon.Off) + about_window.setWindowIcon(icon) + about_window.show() @Slot() @@ -121,11 +147,16 @@ class MainWindow(QMainWindow): dw = VarianceAnalysisWindow(self.model.getData()) dw.exec() + @Slot() + def on_correlationAnalisisAction_triggered(self): + dw = СorrelationAnalysisWindow(self.model.getData()) + dw.exec() + def closeEvent(self, event): if self.isDataChanged: file = '' if self.fileModel.file_name: - file = '\nФайл сохранения:' + self.fileModel.file_name + file = '\nФайл сохранения: ' + self.fileModel.file_name msgBox = buildMessageBox \ ('Завершение работы', diff --git a/statapp/models/correlation_analysis_model.py b/statapp/models/correlation_analysis_model.py new file mode 100644 index 0000000..3b8403d --- /dev/null +++ b/statapp/models/correlation_analysis_model.py @@ -0,0 +1,23 @@ +from PySide2.QtCore import QModelIndex, Qt + +from statapp.models.ro_table_model import ROTableModel +from statapp.models.utils import yx_header + + +class CorrelationAnalysisModel(ROTableModel): + def __init__(self, data): + super().__init__(data) + + def getHorizontalHeader(self): + return yx_header(self.columnCount(QModelIndex())) + + def getVerticalHeader(self): + return yx_header(self.rowCount(QModelIndex())) + + def data(self, index, role): + if role == Qt.DisplayRole: + if (index.column() <= index.row()): + return float(self._data[index.row(), index.column()]) + else: + None + return None diff --git a/statapp/models/fileslc_model.py b/statapp/models/fileslc_model.py index 4bb8d2d..683af7e 100644 --- a/statapp/models/fileslc_model.py +++ b/statapp/models/fileslc_model.py @@ -37,12 +37,13 @@ class FileSLCModel: self.file_name, _ = QFileDialog.getOpenFileName(None, "Загрузить файл", "", "Files (*.txt *.csv)") if self.file_name: try: - content = np.genfromtxt(self.file_name, delimiter=',', invalid_raise=True) + content = np.genfromtxt(self.file_name, delimiter=',', invalid_raise=True, ndmin=2) except ValueError as e: QMessageBox.warning \ (None, 'Ошибка', "Ошибка чтения файла!\nФайл нельзя открыть или файл неверного формата") + self.file_name = None return None return content diff --git a/statapp/models/input_values_model.py b/statapp/models/input_values_model.py index 75ddc41..ecf5eda 100644 --- a/statapp/models/input_values_model.py +++ b/statapp/models/input_values_model.py @@ -28,7 +28,7 @@ class InputValuesModel(EditableTableModel): super().__init__(data) def getHorizontalHeader(self): - return yx_header(self.rowCount(QModelIndex())) + return yx_header(self.columnCount(QModelIndex())) def getY(self): return self._data[:, 0] diff --git a/statapp/ui/correlation_analysis_window.ui b/statapp/ui/correlation_analysis_window.ui new file mode 100644 index 0000000..83e3b08 --- /dev/null +++ b/statapp/ui/correlation_analysis_window.ui @@ -0,0 +1,28 @@ + + + CorrelationAnalysisWindow + + + + 0 + 0 + 630 + 400 + + + + Корреляционный анализ + + + + + + + + + + + + + + diff --git a/statapp/ui/main_window.ui b/statapp/ui/main_window.ui index 850ad4c..37a6252 100644 --- a/statapp/ui/main_window.ui +++ b/statapp/ui/main_window.ui @@ -40,7 +40,7 @@ 0 0 800 - 27 + 21 @@ -63,6 +63,7 @@ Анализ данных + @@ -117,6 +118,11 @@ Дисперсионный анализ + + + Корреляционный анализ + + diff --git a/statapp/ui/ui_correlation_analysis_window.py b/statapp/ui/ui_correlation_analysis_window.py new file mode 100644 index 0000000..b71840a --- /dev/null +++ b/statapp/ui/ui_correlation_analysis_window.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- + +################################################################################ +## Form generated from reading UI file 'correlation_analysis_window.ui' +## +## Created by: Qt User Interface Compiler version 5.15.2 +## +## WARNING! All changes made in this file will be lost when recompiling UI file! +################################################################################ + +from PySide2.QtCore import * +from PySide2.QtGui import * +from PySide2.QtWidgets import * + + +class Ui_CorrelationAnalysisWindow(object): + def setupUi(self, CorrelationAnalysisWindow): + if not CorrelationAnalysisWindow.objectName(): + CorrelationAnalysisWindow.setObjectName(u"CorrelationAnalysisWindow") + CorrelationAnalysisWindow.resize(630, 400) + self.gridLayout_2 = QGridLayout(CorrelationAnalysisWindow) + self.gridLayout_2.setObjectName(u"gridLayout_2") + self.gridLayout = QGridLayout() + self.gridLayout.setObjectName(u"gridLayout") + self.tableView = QTableView(CorrelationAnalysisWindow) + self.tableView.setObjectName(u"tableView") + + self.gridLayout.addWidget(self.tableView, 0, 0, 1, 1) + + + self.gridLayout_2.addLayout(self.gridLayout, 0, 0, 1, 1) + + + self.retranslateUi(CorrelationAnalysisWindow) + + QMetaObject.connectSlotsByName(CorrelationAnalysisWindow) + # setupUi + + def retranslateUi(self, CorrelationAnalysisWindow): + CorrelationAnalysisWindow.setWindowTitle(QCoreApplication.translate("CorrelationAnalysisWindow", u"\u041a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None)) + # retranslateUi + diff --git a/statapp/ui/ui_main_window.py b/statapp/ui/ui_main_window.py index 238cad9..9ca4770 100644 --- a/statapp/ui/ui_main_window.py +++ b/statapp/ui/ui_main_window.py @@ -51,6 +51,8 @@ class Ui_MainWindow(object): self.closefileaction.setObjectName(u"closefileaction") self.varianceAnalysisAction = QAction(MainWindow) self.varianceAnalysisAction.setObjectName(u"varianceAnalysisAction") + self.correlationAnalisisAction = QAction(MainWindow) + self.correlationAnalisisAction.setObjectName(u"correlationAnalisisAction") self.centralwidget = QWidget(MainWindow) self.centralwidget.setObjectName(u"centralwidget") self.gridLayout = QGridLayout(self.centralwidget) @@ -70,7 +72,7 @@ class Ui_MainWindow(object): MainWindow.setCentralWidget(self.centralwidget) self.menubar = QMenuBar(MainWindow) self.menubar.setObjectName(u"menubar") - self.menubar.setGeometry(QRect(0, 0, 800, 27)) + self.menubar.setGeometry(QRect(0, 0, 800, 21)) self.filemenu = QMenu(self.menubar) self.filemenu.setObjectName(u"filemenu") self.generatemenu = QMenu(self.menubar) @@ -97,6 +99,7 @@ class Ui_MainWindow(object): self.generatemenu.addAction(self.generateYaction) self.generatemenu.addAction(self.generateXaction) self.analyzemenu.addAction(self.varianceAnalysisAction) + self.analyzemenu.addAction(self.correlationAnalisisAction) self.helpmenu.addAction(self.aboutmenuaction) self.retranslateUi(MainWindow) @@ -113,6 +116,7 @@ class Ui_MainWindow(object): self.savefileaction.setText(QCoreApplication.translate("MainWindow", u"\u0421\u043e\u0445\u0440\u0430\u043d\u0438\u0442\u044c", None)) self.closefileaction.setText(QCoreApplication.translate("MainWindow", u"\u0417\u0430\u043a\u0440\u044b\u0442\u044c", None)) self.varianceAnalysisAction.setText(QCoreApplication.translate("MainWindow", u"\u0414\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None)) + self.correlationAnalisisAction.setText(QCoreApplication.translate("MainWindow", u"\u041a\u043e\u0440\u0440\u0435\u043b\u044f\u0446\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None)) self.label.setText(QCoreApplication.translate("MainWindow", u"\u0421\u0422\u0410\u0422\u0418\u0421\u0422\u0418\u0427\u0415\u0421\u041a\u0418\u0415 \u0414\u0410\u041d\u041d\u042b\u0415", None)) self.filemenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0424\u0430\u0439\u043b", None)) self.generatemenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0435\u0439", None)) @@ -120,3 +124,4 @@ class Ui_MainWindow(object): self.modelmenu.setTitle(QCoreApplication.translate("MainWindow", u"\u041c\u043e\u0434\u0435\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435", None)) self.helpmenu.setTitle(QCoreApplication.translate("MainWindow", u"\u0421\u043f\u0440\u0430\u0432\u043a\u0430", None)) # retranslateUi + diff --git a/statapp/ui/ui_variance_analysis_window.py b/statapp/ui/ui_variance_analysis_window.py index 5687d47..0f6c488 100644 --- a/statapp/ui/ui_variance_analysis_window.py +++ b/statapp/ui/ui_variance_analysis_window.py @@ -36,7 +36,7 @@ class Ui_VarianceAnalysisWindow(object): def setupUi(self, VarianceAnalysisWindow): if not VarianceAnalysisWindow.objectName(): VarianceAnalysisWindow.setObjectName(u"VarianceAnalysisWindow") - VarianceAnalysisWindow.resize(942, 606) + VarianceAnalysisWindow.resize(630, 400) self.gridLayout_2 = QGridLayout(VarianceAnalysisWindow) self.gridLayout_2.setObjectName(u"gridLayout_2") self.gridLayout = QGridLayout() @@ -58,3 +58,4 @@ class Ui_VarianceAnalysisWindow(object): def retranslateUi(self, VarianceAnalysisWindow): VarianceAnalysisWindow.setWindowTitle(QCoreApplication.translate("VarianceAnalysisWindow", u"\u0414\u0438\u0441\u043f\u0435\u0440\u0441\u0438\u043e\u043d\u043d\u044b\u0439 \u0430\u043d\u0430\u043b\u0438\u0437", None)) # retranslateUi + diff --git a/statapp/ui/variance_analysis_window.ui b/statapp/ui/variance_analysis_window.ui index 80de4a0..c4d9546 100644 --- a/statapp/ui/variance_analysis_window.ui +++ b/statapp/ui/variance_analysis_window.ui @@ -6,8 +6,8 @@ 0 0 - 942 - 606 + 630 + 400