我在Qt设计器中设计了一个UI,由1个按钮和1个QTableView
组成。该按钮用于浏览 Excel,根据我的代码对其进行操作并将结果显示在 TableView
中。 。这是我的代码:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
import numpy as np
import pandas as pd
import glob
import os
import csv
from itertools import combinations
from PyQt5.QtWidgets import QDialog, QApplication
class DataFrameModel(QtCore.QAbstractTableModel):
DtypeRole = QtCore.Qt.UserRole + 1000
ValueRole = QtCore.Qt.UserRole + 1001
def __init__(self, df=pd.DataFrame(), parent=None):
super(DataFrameModel, self).__init__(parent)
self._dataframe = df
def setDataFrame(self, dataframe):
self.beginResetModel()
self._dataframe = dataframe.copy()
self.endResetModel()
def dataFrame(self):
return self._dataframe
dataFrame = QtCore.pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame)
@QtCore.pyqtSlot(int, QtCore.Qt.Orientation, result=str)
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self._dataframe.columns[section]
else:
return str(self._dataframe.index[section])
return QtCore.QVariant()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._dataframe.index)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._dataframe.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or not (0 <= index.row() < self.rowCount() \
and 0 <= index.column() < self.columnCount()):
return QtCore.QVariant()
row = self._dataframe.index[index.row()]
col = self._dataframe.columns[index.column()]
dt = self._dataframe[col].dtype
val = self._dataframe.iloc[row][col]
if role == QtCore.Qt.DisplayRole:
return str(val)
elif role == DataFrameModel.ValueRole:
return val
if role == DataFrameModel.DtypeRole:
return dt
return QtCore.QVariant()
def roleNames(self):
roles = {
QtCore.Qt.DisplayRole: b'display',
DataFrameModel.DtypeRole: b'dtype',
DataFrameModel.ValueRole: b'value'
}
return roles
class Ui_Rulepriority(object):
def setupUi(self, Rulepriority):
Rulepriority.setObjectName("Rulepriority")
Rulepriority.resize(820, 480)
self.verticalLayout = QtWidgets.QVBoxLayout(Rulepriority)
self.verticalLayout.setObjectName("verticalLayout")
self.OpenCsv = QtWidgets.QPushButton(Rulepriority)
self.OpenCsv.setObjectName("OpenCsv")
self.verticalLayout.addWidget(self.OpenCsv)
self.OpenCsv.clicked.connect(self.file_open)
self.tableView = QtWidgets.QTableView(Rulepriority)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.setObjectName("tableView")
self.verticalLayout.addWidget(self.tableView)
self.retranslateUi(Rulepriority)
self.OpenCsv.clicked.connect(self.tableView.show)
QtCore.QMetaObject.connectSlotsByName(Rulepriority)
def retranslateUi(self, Rulepriority):
_translate = QtCore.QCoreApplication.translate
Rulepriority.setWindowTitle(_translate("Rulepriority", "Violation Solving Prioritization tool"))
self.OpenCsv.setText(_translate("Rulepriority", "Browse excel and get solving probability"))
Rulepriority.setWindowIcon(QtGui.QIcon('favicon.ico'))
def file_open(self):
path, _ = QtWidgets.QFileDialog.getOpenFileName(Rulepriority, 'Open csv', QtCore.QDir.rootPath(),
'Data_*.xlsx')
df1 = pd.read_excel(path)
df2 = df1.set_index(['Priority', 'RID to solve', 'Probability', 'RID per probability', 'Remarks']).sort_values(by=['Priority'],
ascending=True)
model = DataFrameModel(df2)
self.tableView.setModel(model)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Rulepriority = QtWidgets.QDialog()
ui = Ui_Rulepriority()
ui.setupUi(Rulepriority)
Rulepriority.show()
sys.exit(app.exec_())
这里def file_open(self)
用于浏览excel表格。用于在 QTableView
中显示 pandas DataFrame ,我正在使用class DataFrameModel(QtCore.QAbstractTableModel)
我从这个答案借来的How to display a Pandas data frame with PyQt5/PySide2
这是我浏览的数据的样子:
为此,我使用此代码:
df2 = df1.set_index(['Priority', 'RID to solve', 'Probability', 'RID per probability', 'Remarks']).sort_values(by=['Priority'],
ascending=True)
但是当我尝试在前端显示相同的结果时,我得到像这样的逗号分隔结果:
如果你们能帮我得到上面的显示格式,我将不胜感激。
最佳答案
解决了问题。我发现不寻常的索引导致了问题,所以,
而不是:
df2 = df1.set_index(['Priority', 'RID to solve', 'Probability', 'RID per probability', 'Remarks']).sort_values(by=['Priority'],
ascending=True)
我用的是这个:
cols = ['Priority','RID to solve']
dm = df1[cols].apply(lambda x: x.duplicated())
df1[cols]= df1[cols].mask(m, '')
这段代码的作用是,首先用缺失值替换重复值,然后在数据帧列上屏蔽它们以获得如下结果:
这是经过上述审核的完整代码:
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtGui import QIcon
import numpy as np
import pandas as pd
import glob
import os
import csv
from itertools import combinations
from PyQt5.QtWidgets import QDialog, QApplication
class DataFrameModel(QtCore.QAbstractTableModel):
DtypeRole = QtCore.Qt.UserRole + 1000
ValueRole = QtCore.Qt.UserRole + 1001
def __init__(self, df=pd.DataFrame(), parent=None):
super(DataFrameModel, self).__init__(parent)
self._dataframe = df
def setDataFrame(self, dataframe):
self.beginResetModel()
self._dataframe = dataframe.copy()
self.endResetModel()
def dataFrame(self):
return self._dataframe
dataFrame = QtCore.pyqtProperty(pd.DataFrame, fget=dataFrame, fset=setDataFrame)
@QtCore.pyqtSlot(int, QtCore.Qt.Orientation, result=str)
def headerData(self, section: int, orientation: QtCore.Qt.Orientation, role: int = QtCore.Qt.DisplayRole):
if role == QtCore.Qt.DisplayRole:
if orientation == QtCore.Qt.Horizontal:
return self._dataframe.columns[section]
else:
return str(self._dataframe.index[section])
return QtCore.QVariant()
def rowCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return len(self._dataframe.index)
def columnCount(self, parent=QtCore.QModelIndex()):
if parent.isValid():
return 0
return self._dataframe.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if not index.isValid() or not (0 <= index.row() < self.rowCount() \
and 0 <= index.column() < self.columnCount()):
return QtCore.QVariant()
row = self._dataframe.index[index.row()]
col = self._dataframe.columns[index.column()]
dt = self._dataframe[col].dtype
val = self._dataframe.iloc[row][col]
if role == QtCore.Qt.DisplayRole:
return str(val)
elif role == DataFrameModel.ValueRole:
return val
if role == DataFrameModel.DtypeRole:
return dt
return QtCore.QVariant()
def roleNames(self):
roles = {
QtCore.Qt.DisplayRole: b'display',
DataFrameModel.DtypeRole: b'dtype',
DataFrameModel.ValueRole: b'value'
}
return roles
class Ui_Rulepriority(object):
def setupUi(self, Rulepriority):
Rulepriority.setObjectName("Rulepriority")
Rulepriority.resize(820, 480)
self.verticalLayout = QtWidgets.QVBoxLayout(Rulepriority)
self.verticalLayout.setObjectName("verticalLayout")
self.OpenCsv = QtWidgets.QPushButton(Rulepriority)
self.OpenCsv.setObjectName("OpenCsv")
self.verticalLayout.addWidget(self.OpenCsv)
self.OpenCsv.clicked.connect(self.file_open)
self.tableView = QtWidgets.QTableView(Rulepriority)
self.tableView.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContents)
self.tableView.setObjectName("tableView")
self.verticalLayout.addWidget(self.tableView)
QtCore.QFileSystemWatcher()
self.retranslateUi(Rulepriority)
self.OpenCsv.clicked.connect(self.tableView.show)
QtCore.QMetaObject.connectSlotsByName(Rulepriority)
def retranslateUi(self, Rulepriority):
_translate = QtCore.QCoreApplication.translate
Rulepriority.setWindowTitle(_translate("Rulepriority", "Violation Solving Prioritization tool"))
self.OpenCsv.setText(_translate("Rulepriority", "Browse excel and get solving probability"))
Rulepriority.setWindowIcon(QtGui.QIcon('favicon.ico'))
def file_open(self):
path, _ = QtWidgets.QFileDialog.getOpenFileName(Rulepriority, 'Open csv', QtCore.QDir.rootPath(),
'Data_*.xlsx')
df1 = pd.read_excel(path)
cols = ['Priority', 'RID to solve']
dm = df1[cols].apply(lambda x: x.duplicated())
df1[cols] = df1[cols].mask(dm, '')
model = DataFrameModel(df1)
self.tableView.setModel(model)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
Rulepriority = QtWidgets.QDialog()
ui = Ui_Rulepriority()
ui.setupUi(Rulepriority)
Rulepriority.show()
sys.exit(app.exec_())
干杯:)
关于python - 在 PyQt5 的 TableView 中显示 pandas DataFrame,其中列设置为索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58234343/