2015-07-17 12 views
8

Jestem bardzo nowy w PyQt i staram się zapełnić formant QTableView.Najszybszy sposób na wypełnienie QTableView z ramki danych Pandy

Mój kod jest następujący:

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) 

Właściwie w kodzie I uda się zapełnić QListView, ale wartości ustawić na QTableView nie są wyświetlane, również można zobaczyć, że obcięty wiersze do 10, ponieważ wyświetlenie setek wierszy ramki danych trwa wiecznie.

Jaki jest najszybszy sposób wypełnienia modelu tabeli z ramki danych pandy?

Z góry dziękuję.

+0

Czy przetestowałeś rozwiązanie podane przez Wolpha, aby sprawdzić, czy zapewnia on lepszą wydajność? – ekhumoro

+0

Jeszcze nie, również nie do końca rozumiem, więc zajmie mi to trochę czasu. –

+0

Zrobiłem małe testowanie. W przypadku tabeli z 25 kolumnami i 10000 wierszy niestandardowy model jest około 40 razy szybszy (a różnica wydajności rośnie geometrycznie wraz ze wzrostem liczby wierszy/kolumn). Używało to prostej listy-list dla danych, więc wydaje się, że tworzenie wszystkich tych instancji 'QStandardItem' jest głównym wąskim gardłem. – ekhumoro

Odpowiedz

12

Osobiście chciałbym po prostu utworzyć własną klasę modelu, aby jej obsługa była nieco łatwiejsza.

Na przykład:

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

Witam, pojawia się następujący błąd: 'return QtCore.QVariant() TypeError: PyQt4.QtCore.QVariant reprezentuje odwzorowany typ i nie można go utworzyć w instancji' –

11

to działa:

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 

Używanie go tak:

model = PandasModel(your_pandas_data_frame) 
your_tableview.setModel(model) 

czytam here uniknąć QVariant() z pyqt 4.6.

+2

Stara odpowiedź, ale nadal dobra. Jeśli chcesz, aby indeks twojej ramki danych pojawił się w wierszu, możesz zmodyfikować nagłówek metody w następujący sposób: 'def nagłówekData (self, rowcol, orientacja, rola): jeśli orientacja == QtCore.Qt.Horizontal i rola = = QtCore.Qt.DisplayRole: return self._data.columns [rowcol] jeśli orientacja == QtCore.Qt.Vertical i rola == QtCore.Qt.DisplayRole: return self._data.index [rowcol] return Brak ' – Wli

+0

To działa, ale jak mogę uczynić model edytowalnym, a następnie przenieść go z powrotem do ramki danych? Obecnie nie można go nawet edytować. – Nickpick

+0

https://github.com/SanPen/GridCal/blob/master/UnderDevelopment/GridCal/gui/GuiFunctions.py. To jest jeden projekt Open Source, w którym opracowałem ten model. –

3

W rzeczywistości jest jakiś kod w pandas wspierający integrację z Qt.

W chwili pisania tego odpowiedź, najnowsza wersja pandy jest 0.18.1 i można zrobić:

from pandas.sandbox.qtpandas import DataFrameModel, DataFrameWidget 

Ten kod wydaje się być sprzężony PySide, jednak powinien on być stosunkowo trywialne, aby pracować z PyQt. Również ten kod został uznany za przestarzały, a ostrzeżenie mówi, że moduł zostanie usunięty w przyszłości.

Na szczęście ekstrakcji że w oddzielnej projektu GitHub nazywa pandas-qt:

https://github.com/datalyze-solutions/pandas-qt

chciałbym spróbować w obsłudze, że przed próbą rozwałkować mój własny model i widok realizację.

+0

Witam Chcę tylko dodać, pandas-qt nie obsługuje python3 i wygląda na to, że prawdopodobnie przyzwyczajenie. W międzyczasie możesz użyć [qtpandas] (https://github.com/draperjames/qtpandas) 'pip install qtpandas' –

1

Znalazłem wszystkie proponowane odpowiedzi boleśnie wolno dla DataFrames z ponad 1000 wierszy. To, co działa dla mnie niesamowicie szybko:

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 
Powiązane problemy