안녕하세요. 다름아니라 PyQt5
로 여러 개의 값을 입력받아서 그것을 결국에는 화면에 그래프로 출력하고, 입력받은 데이터를 계산하고 필터링해서 엑셀로 저장할 수도 있는 프로그램을 만들고 싶은 학생입니다. 현재 어느정도 구글링해가면서 코드를 작성해봤는데, 1만번까지는 (빠르지는 않지만) 1분 안에는 실행되는 것 같은데 10만번을 돌리면 프로그램이 아예 멈춰버리네요.
조금 더 효율적으로 반복을 수행할 수 있는 방법이 있을까해서 글을 올립니다. 아래 코드 중 # for Loop 실행 메소드에서 self.data
를 수행하는 데 오래걸리는 것 같습니다.
결국 제가 하려는 것은 어떤 금액을 입력하고 그 금액의 +범위, -범위를 지정해서 랜덤으로 추출한 후 해당 범위로부터의 오차들의 표준편차를 구하려 합니다.
import sys
import random
from PyQt5.Qt import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets
import pandas as pd
import matplotlib.pyplot as pp
class BP3_UI(QMainWindow):
def __init__(self):
super().__init__()
self.setGeometry(100, 250, 500, 800)
self.resize(985, 760)
self.setWindowTitle("BP3")
self.UI()
'''
아이콘 추가 시
self.setWindowIcon(QIcon("icon.png"))
'''
def UI(self):
# 라벨 폰트
font = QtGui.QFont()
font.setFamily("굴림")
font.setPointSize(10)
'''
# 메뉴바 생성
self.statusBar()
menubar = self.menuBar()
menubar.setNativeMenuBar(False)
menu_1 = menubar.addMenu('&정보')
'''
# 라벨 생성
self.label_cnt_0 = QLabel("[1] 반복 횟수 : ", self)
self.label_cnt_0.setGeometry(20, 40, 121, 16)
self.label_cnt_0.setFont(font)
self.label_input_0 = QLabel("[2] 예비 가격 : ", self)
self.label_input_0.setGeometry(QtCore.QRect(20, 70, 121, 16))
self.label_input_0.setFont(font)
self.label_input_1 = QLabel("[3] +범위 예가율 : ", self)
self.label_input_1.setGeometry(QtCore.QRect(20, 130, 121, 16))
self.label_input_1.setFont(font)
self.label_cnt_1 = QLabel("[4] +범위 추출 수량 : ", self)
self.label_cnt_1.setGeometry(20, 160, 131, 16)
self.label_cnt_1.setFont(font)
self.label_input_2 = QLabel("[5] -범위 예가율 : ", self)
self.label_input_2.setGeometry(QtCore.QRect(20, 220, 121, 16))
self.label_input_2.setFont(font)
self.label_cnt_2 = QLabel("[6] -범위 추출 수량 : ", self)
self.label_cnt_2.setGeometry(20, 250, 131, 16)
self.label_cnt_2.setFont(font)
self.label_cnt_3 = QLabel("[7] 최종 출력 수량 : ", self)
self.label_cnt_3.setGeometry(20, 310, 121, 16)
self.label_cnt_3.setFont(font)
self.label_unit_1 = QLabel("번", self)
self.label_unit_1.setGeometry(260, 40, 21, 16)
self.label_unit_1.setFont(font)
self.label_unit_2 = QLabel("원", self)
self.label_unit_2.setGeometry(260, 70, 21, 16)
self.label_unit_2.setFont(font)
self.label_unit_3 = QLabel("%", self)
self.label_unit_3.setGeometry(260, 130, 21, 16)
self.label_unit_3.setFont(font)
self.label_unit_4 = QLabel("개", self)
self.label_unit_4.setGeometry(260, 160, 21, 16)
self.label_unit_4.setFont(font)
self.label_unit_5 = QLabel("%", self)
self.label_unit_5.setGeometry(260, 220, 21, 16)
self.label_unit_5.setFont(font)
self.label_unit_6 = QLabel("개", self)
self.label_unit_6.setGeometry(260, 250, 21, 16)
self.label_unit_6.setFont(font)
self.label_unit_7 = QLabel("개", self)
self.label_unit_7.setGeometry(260, 310, 21, 16)
self.label_unit_7.setFont(font)
# 라인에딧(텍스트 박스) 생성
self.lineedit_cnt_0 = QLineEdit(self)
self.lineedit_cnt_0.setGeometry(120, 40, 131, 20)
self.lineedit_cnt_0.setFont(font)
self.lineedit_cnt_0.setPlaceholderText("횟수 입력")
self.lineedit_cnt_0.setDragEnabled(True)
self.lineedit_input_0 = QLineEdit(self)
self.lineedit_input_0.setGeometry(120, 70, 131, 20)
self.lineedit_input_0.setFont(font)
self.lineedit_input_0.setPlaceholderText("예상가격 입력")
self.lineedit_input_0.setDragEnabled(True)
self.lineedit_input_1 = QLineEdit(self)
self.lineedit_input_1.setGeometry(140, 130, 111, 20)
self.lineedit_input_1.setFont(font)
self.lineedit_input_1.setPlaceholderText("예가율 입력")
self.lineedit_input_1.setDragEnabled(True)
self.lineedit_cnt_1 = QLineEdit(self)
self.lineedit_cnt_1.setGeometry(160, 160, 91, 20)
self.lineedit_cnt_1.setFont(font)
self.lineedit_cnt_1.setPlaceholderText("수량 입력")
self.lineedit_cnt_1.setDragEnabled(True)
self.lineedit_input_2 = QLineEdit(self)
self.lineedit_input_2.setGeometry(140, 220, 111, 20)
self.lineedit_input_2.setFont(font)
self.lineedit_input_2.setPlaceholderText("예가율 입력")
self.lineedit_input_2.setDragEnabled(True)
self.lineedit_cnt_2 = QLineEdit(self)
self.lineedit_cnt_2.setGeometry(160, 250, 91, 20)
self.lineedit_cnt_2.setFont(font)
self.lineedit_cnt_2.setPlaceholderText("수량 입력")
self.lineedit_cnt_2.setDragEnabled(True)
self.lineedit_cnt_3 = QLineEdit(self)
self.lineedit_cnt_3.setGeometry(150, 310, 101, 20)
self.lineedit_cnt_3.setFont(font)
self.lineedit_cnt_3.setPlaceholderText("수량 입력")
self.lineedit_cnt_3.setDragEnabled(True)
# 구분선 생성
self.line_0_1 = QFrame(self)
self.line_0_1.setGeometry(20, 10, 80, 16)
self.line_0_1.setFrameShape(QFrame.HLine)
self.line_0_1.setFrameShadow(QFrame.Sunken)
self.label_div_0 = QLabel("[기초 입력사항]", self)
self.label_div_0.setGeometry(90, 10, 121, 16)
self.label_div_0.setFont(font)
self.label_div_0.setAlignment(QtCore.Qt.AlignCenter)
self.line_0_2 = QFrame(self)
self.line_0_2.setGeometry(200, 10, 81, 16)
self.line_0_2.setFrameShape(QFrame.HLine)
self.line_0_2.setFrameShadow(QFrame.Sunken)
self.line_1_1 = QFrame(self)
self.line_1_1.setGeometry(20, 100, 77, 16)
self.line_1_1.setFrameShape(QFrame.HLine)
self.line_1_1.setFrameShadow(QFrame.Sunken)
self.label_div_1 = QLabel("[+범위 입력사항]", self)
self.label_div_1.setGeometry(90, 100, 121, 16)
self.label_div_1.setFont(font)
self.label_div_1.setAlignment(QtCore.Qt.AlignCenter)
self.line_1_2 = QFrame(self)
self.line_1_2.setGeometry(203, 100, 81, 16)
self.line_1_2.setFrameShape(QFrame.HLine)
self.line_1_2.setFrameShadow(QFrame.Sunken)
self.line_2_1 = QFrame(self)
self.line_2_1.setGeometry(20, 190, 77, 16)
self.line_2_1.setFrameShape(QFrame.HLine)
self.line_2_1.setFrameShadow(QFrame.Sunken)
self.label_div_2 = QLabel("[-범위 입력사항]", self)
self.label_div_2.setGeometry(90, 190, 121, 16)
self.label_div_2.setFont(font)
self.label_div_2.setAlignment(QtCore.Qt.AlignCenter)
self.line_2_2 = QFrame(self)
self.line_2_2.setGeometry(203, 190, 81, 16)
self.line_2_2.setFrameShape(QFrame.HLine)
self.line_2_2.setFrameShadow(QFrame.Sunken)
self.line_3_1 = QFrame(self)
self.line_3_1.setGeometry(20, 280, 80, 20)
self.line_3_1.setFrameShape(QFrame.HLine)
self.line_3_1.setFrameShadow(QFrame.Sunken)
self.label_div_3 = QLabel("[최종 입력사항]", self)
self.label_div_3.setGeometry(90, 280, 121, 16)
self.label_div_3.setFont(font)
self.label_div_3.setAlignment(QtCore.Qt.AlignCenter)
self.line_3_2 = QFrame(self)
self.line_3_2.setGeometry(200, 280, 81, 20)
self.line_3_2.setFrameShape(QFrame.HLine)
self.line_3_2.setFrameShadow(QFrame.Sunken)
# 버튼 생성
self.btn_1 = QtWidgets.QPushButton("실행", self)
self.btn_1.setGeometry(20, 370, 81, 31)
self.btn_1.setFont(font)
self.btn_1.clicked.connect(self.btn_1_clicked) # 실행 버튼 이벤트 메소드 연결
self.btn_2 = QPushButton("리셋", self)
self.btn_2.setGeometry(110, 370, 81, 31)
self.btn_2.setFont(font)
self.btn_2.clicked.connect(self.btn_2_clicked) # 리셋 버튼 이벤트 메소드 연결
self.btn_3 = QPushButton("저장", self)
self.btn_3.setGeometry(200, 370, 81, 31)
self.btn_3.setFont(font)
self.btn_3.clicked.connect(self.btn_3_clicked) # 저장 버튼 이벤트 메소드 연결
# 종료버튼 누를 시 대화창 생성 메소드
def closeEvent(self, QCloseEvent):
question = QMessageBox.question(self, "종료 확인", "종료를 하시겠습니까?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No)
QCloseEvent.accept() if question == QMessageBox.Yes else QCloseEvent.ignore()
# 테이블 생성 메소드
def make_Table(self):
self.data = pd.DataFrame(columns=['cnt', 'previous', 'rate', 'rated', 'rated_beta', 'condition', 'condition_beta'])
self.InputValue()
self.cnt_0 = int(self.lineedit_cnt_0.text())
self.cnt_1 = int(self.lineedit_cnt_1.text())
self.cnt_2 = int(self.lineedit_cnt_2.text())
self.cnt_3 = int(self.lineedit_cnt_3.text())
self.input_0 = int(self.lineedit_input_0.text())
self.range_1 = int(self.input_0 + self.input_0 * self.input_1 / 100)
self.range_2 = int(self.input_0 - self.input_0 * self.input_2 / 100)
self.Start()
self.List()
self.DeleteNull()
self.Category()
# LineEdit 자료형 자동 변환 메소드
def InputValue(self):
val_int = QIntValidator()
val_double = QDoubleValidator()
self.input_1 = float(self.lineedit_input_1.text()) if '.' in self.lineedit_input_1.text() else int(self.lineedit_input_1.text())
self.input_2 = float(self.lineedit_input_2.text()) if '.' in self.lineedit_input_2.text() else int(self.lineedit_input_2.text())
# for Loop 실행 메소드
def Start(self):
for i in range(0, self.cnt_0) :
self.list_sum = random.sample(range(self.input_0, self.range_1), self.cnt_1) + random.sample(range(self.range_2, self.input_0), self.cnt_2)
self.list_3 = random.sample(self.list_sum, self.cnt_3)
self.avg = sum(self.list_3) / self.cnt_3
self.d_rate = self.avg / self.input_0
self.condition = float((self.input_1 * 100 - 5 * i) / 10000)
self.data = self.data.append(pd.DataFrame([[i+1, self.avg, self.d_rate, self.d_rate-1, int((self.d_rate-1)*10000), "" if self.condition < 0 and round(-self.input_1/100, 4) > round(self.condition, 4) else self.condition, "" if self.condition < 0 and round(-self.input_1/100, 4) > round(self.condition, 4) else int(self.condition*10000)]], columns=['cnt', 'previous', 'rate', 'rated', 'rated_beta', 'condition', 'condition_beta']), ignore_index=True)
# 리스트로 변환
def List(self):
self.list_rated = self.data.iloc[:, 4].tolist()
self.condition_tolist = self.data.iloc[:, 6].tolist()
# 변환한 리스트 안에 빈 데이터('') 제거
def DeleteNull(self):
self.list_condition = [x for x in self.condition_tolist if x]
self.list_condition.append(0)
self.list_condition.sort()
# 카테고리화
def Category(self):
self.category = pd.cut(self.list_rated, self.list_condition)
self.series = self.category.value_counts()
self.value = self.category.value_counts().to_frame() # Category → DataFrame
self.value = self.value.reset_index() # 새로운 index로 변경
self.value.columns = ["range", "count"]
self.data_sum = pd.merge(self.data, self.value, how="outer", left_index=True, right_index=True) # 데이터 결합
# 그래프 생성 메소드
def make_Graph(self):
self.graph = self.value.plot.barh(x='range', y='count')
pp.show()
# 버튼 '실행' 클릭 이벤트 메소드 생성
def btn_1_clicked(self):
self.make_Table()
self.make_Graph()
# 버튼 '리셋' 클릭 이벤트 메소드 생성
def btn_2_clicked(self):
self.lineedit_cnt_0.setText("")
self.lineedit_cnt_1.setText("")
self.lineedit_cnt_2.setText("")
self.lineedit_cnt_3.setText("")
self.lineedit_input_0.setText("")
self.lineedit_input_1.setText("")
self.lineedit_input_2.setText("")
# 버튼 '저장' 클릭 이벤트 메소드 생성
def btn_3_clicked(self):
print("저장")
if __name__ == "__main__":
app = QApplication(sys.argv)
window = BP3_UI()
window.show()
app.exec_()