我是PyQt的新手,我正在努力填充QTableView控件。
我的代码如下:
def data_frame_to_ui(self, data_frame):
"""
Displays a pandas data frame into the GUI
"""
list_model = QtGui.QStandardItemModel()
i = 0
for val in data_frame.columns:
# for the list model
if i > 0:
item = QtGui.QStandardItem(val)
#item.setCheckable(True)
item.setEditable(False)
list_model.appendRow(item)
i += 1
self.ui.profilesListView.setModel(list_model)
# for the table model
table_model = QtGui.QStandardItemModel()
# set table headers
table_model.setColumnCount(data_frame.columns.size)
table_model.setHorizontalHeaderLabels(data_frame.columns.tolist())
self.ui.profileTableView.horizontalHeader().setStretchLastSection(True)
# fill table model data
for row_idx in range(10): #len(data_frame.values)
row = list()
for col_idx in range(data_frame.columns.size):
val = QtGui.QStandardItem(str(data_frame.values[row_idx][col_idx]))
row.append(val)
table_model.appendRow(row)
# set table model to table object
self.ui.profileTableView.setModel(table_model)
实际上在代码中我成功填充了QListView,但是我没有显示我设置到QTableView的值,你也可以看到我将行截断为10,因为显示数百行数据需要永远帧。
那么,从pandas数据框填充表模型的最快方法是什么?
提前致谢。
答案 0 :(得分:16)
就个人而言,我只想创建自己的模型类,使其处理起来更容易一些。
例如:
import sys
from PyQt4 import QtCore, QtGui
Qt = QtCore.Qt
class PandasModel(QtCore.QAbstractTableModel):
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def data(self, index, role=Qt.DisplayRole):
if index.isValid():
if role == Qt.DisplayRole:
return QtCore.QVariant(str(
self._data.values[index.row()][index.column()]))
return QtCore.QVariant()
if __name__ == '__main__':
application = QtGui.QApplication(sys.argv)
view = QtGui.QTableView()
model = PandasModel(your_pandas_data)
view.setModel(model)
view.show()
sys.exit(application.exec_())
答案 1 :(得分:13)
这有效:
class PandasModel(QtCore.QAbstractTableModel):
"""
Class to populate a table view with a pandas dataframe
"""
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
return str(self._data.values[index.row()][index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[col]
return None
像这样使用它:
model = PandasModel(your_pandas_data_frame)
your_tableview.setModel(model)
我阅读here以避免PyQT 4.6中的QVariant()
。
答案 2 :(得分:4)
我发现所有提议的答案对于1000行以上的DataFrame来说都非常缓慢。什么对我来说非常快:
class PandasModel(QtCore.QAbstractTableModel):
"""
Class to populate a table view with a pandas dataframe
"""
def __init__(self, data, parent=None):
QtCore.QAbstractTableModel.__init__(self, parent)
self._data = data
def rowCount(self, parent=None):
return self._data.shape[0]
def columnCount(self, parent=None):
return self._data.shape[1]
def data(self, index, role=QtCore.Qt.DisplayRole):
if index.isValid():
if role == QtCore.Qt.DisplayRole:
return str(self._data.iloc[index.row(), index.column()])
return None
def headerData(self, col, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[col]
return None
答案 3 :(得分:2)
class ModelListCreateView(GetQuerysetMixin, generics.ListCreateAPIView):
def get_queryset(self):
return get_objects_for_user(self.request.user, 'model.view_model')
实际上有一些代码支持与Qt的集成。
在撰写本回答时,最新的pandas版本为pandas
,您可以这样做:
0.18.1
该代码似乎与PySide相关联,但是使它与PyQt一起使用应该相对微不足道。此外,该代码已被弃用,警告称该模块将在以后删除。
幸运的是,他们将其提取到GitHub中名为from pandas.sandbox.qtpandas import DataFrameModel, DataFrameWidget
的单独项目中:
https://github.com/datalyze-solutions/pandas-qt
在尝试推出自己的模型并查看实现之前,我会尝试使用它。
答案 4 :(得分:1)
除了使用QtCore.QAbstractTableModel,还可以继承QtGui.QStandardItemModel。我发现这种方法更容易支持QTableView发出的handleChanged事件。
from PyQt5 import QtCore, QtGui
class PandasModel(QtGui.QStandardItemModel):
def __init__(self, data, parent=None):
QtGui.QStandardItemModel.__init__(self, parent)
self._data = data
for row in data.values.tolist():
data_row = [ QtGui.QStandardItem("{0:.6f}".format(x)) for x in row ]
self.appendRow(data_row)
return
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def headerData(self, x, orientation, role):
if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
return self._data.columns[x]
if orientation == QtCore.Qt.Vertical and role == QtCore.Qt.DisplayRole:
return self._data.index[x]
return None
答案 5 :(得分:0)
将数据帧写入QtableWidget的简单快捷方式
# Takes a df and writes it to a qtable provided. df headers become qtable headers
@staticmethod
def write_df_to_qtable(df,table):
headers = list(df)
table.setRowCount(df.shape[0])
table.setColumnCount(df.shape[1])
table.setHorizontalHeaderLabels(headers)
# getting data from df is computationally costly so convert it to array first
df_array = df.values
for row in range(df.shape[0]):
for col in range(df.shape[1]):
table.setItem(row, col, QtGui.QTableWidgetItem(str(df_array[row,col])))
答案 6 :(得分:0)
此处是适用于
PyQT5 的完全复制示例 以@Frederick Li的答案为基础,并做了些微修改。
from PyQt5 import QtGui, QtWidgets
from PyQt5.QtCore import Qt
import sys
import pandas as pd
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, obj=None, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.centralwidget = QtWidgets.QWidget(self)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
self.centralwidget.setSizePolicy(sizePolicy)
self.pdtable = QtWidgets.QTableView(self.centralwidget)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.MinimumExpanding, QtWidgets.QSizePolicy.Fixed)
self.pdtable.setSizePolicy(sizePolicy)
dataPD = [['tom', 10.0, 180.3], ['nick', 15.0, 175.7], ['juli', 14.0, 160.6]]
df = pd.DataFrame(dataPD, columns=['Name', 'Age', 'Height'])
print(df.dtypes)
self.model = PandasTableModel(df)
self.pdtable.setModel(self.model)
self.setCentralWidget(self.centralwidget)
class PandasTableModel(QtGui.QStandardItemModel):
def __init__(self, data, parent=None):
QtGui.QStandardItemModel.__init__(self, parent)
self._data = data
for row in data.values.tolist():
data_row = [ QtGui.QStandardItem("{}".format(x)) for x in row ]
self.appendRow(data_row)
return
def rowCount(self, parent=None):
return len(self._data.values)
def columnCount(self, parent=None):
return self._data.columns.size
def headerData(self, x, orientation, role):
if orientation == Qt.Horizontal and role == Qt.DisplayRole:
return self._data.columns[x]
if orientation == Qt.Vertical and role == Qt.DisplayRole:
return self._data.index[x]
return None
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyle("Fusion")
main = MainWindow()
main.show()
main.resize(600, 400)
sys.exit(app.exec_())