私は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データフレームからテーブルモデルを作成する最も速い方法は何ですか?
前もって感謝します。
個人的には、自分のモデルクラスを作成して、処理をやや簡単にするだけです。
例えば:
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_())
これは機能します:
_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)
_
PyQT 4.6以降のQVariant()
を避けるために here を読みます。
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
実際、pandas
にはQtとの統合をサポートするいくつかのコードがあります。
この回答を書いている時点で、最新のpandasバージョンは0.18.1
であり、次のことができます。
from pandas.sandbox.qtpandas import DataFrameModel, DataFrameWidget
そのコードはPySideと連動しているようですが、PyQtで動作させるには比較的簡単なはずです。また、そのコードは非推奨になり、警告はモジュールが将来削除されることを示しています。
幸運にも、彼らはそれをpandas-qt
と呼ばれるGitHubの個別のプロジェクトに抽出しました:
https://github.com/datalyze-solutions/pandas-qt
自分のモデルを展開して実装を表示する前に、それを使用してみます。
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])))
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