从已编辑的PyQt5 QTableView对象保存更新的数据框

时间:2018-11-02 19:37:24

标签: python pandas pyqt5

我目前正在尝试将数据帧加载到PyQt QTableView中,以允许重命名所需的列。重新命名完成后,将新数据框另存为.csv到本地文件夹中。我无法保存更新的QTableView模型。工作流程如下所示。

  1. 阅读我要修改的.csv

  1. 将数据框加载到QTableView中,并在第一行的每一列中都有一个组合框

  1. 能够选择其他选项来重命名列

  1. 为所需列选择所需名称

如果在组合框中选择了某个选项(例如,“默认”),这将很有帮助,它将使所需的列名与原始列名相同。

  1. 将最终数据帧另存为文件到本地文件夹

注意:只有在组合框中具有值的列才保留在最终数据集中。指定为“默认”的列将保留原始列名。

以下代码示例:

form_class = uic.loadUiType("DataProcessing.ui")[0]

class MyWindowClass(QtWidgets.QMainWindow, form_class):
    def __init__(self, parent=None):
        super().__init__()
        self.setupUi(self)

        self.PushButtonDisplay.clicked.connect(self.IP_Data_Display)
        self.PushButtonImport.clicked.connect(self.IP_File_Import)


    def IP_Data_Display(self):
        DT_Disp = self.CBdisplay.currentText()
        data = pd.read_csv('Example.csv')
        data.loc[-1] = pd.Series([np.nan])
        data.index = data.index + 1
        data = data.sort_index()
        model = PandasModel(data)
        self.TView.setModel(model)
        for column in range(model.columnCount()):
            c = QtWidgets.QComboBox()

            c.addItems(['','Option 1','Option 2','Option 3','Option 4','Default'])
            i = self.TView.model().index(0,column)
            self.TView.setIndexWidget(i,c)

    def IP_File_Import(self):
        newModel = self.TView.model()
        data = []
        for row in range(newModel.rowCount()):
            rowRes = []
            for column in range(newModel.columnCount()):
                index = newModel.index(row, column)
                item = newModel.data(index)
                if item != '':
                rowRes.append(item)
            data.append(rowRes)
        dataFrame = pd.DataFrame(data)
        dataFrame.to_csv('Test.csv')#, index=False, header=False)


class PandasModel(QtCore.QAbstractTableModel): 
    def __init__(self, df = pd.DataFrame(), parent=None): 
        QtCore.QAbstractTableModel.__init__(self, parent=parent)
        self._df = df

    def headerData(self, section, orientation, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if orientation == QtCore.Qt.Horizontal:
            try:
                return self._df.columns.tolist()[section]
            except (IndexError, ):
                return QtCore.QVariant()
        elif orientation == QtCore.Qt.Vertical:
            try:
                return self._df.index.tolist()[section]
            except (IndexError, ):
                return QtCore.QVariant()

    def data(self, index, role=QtCore.Qt.DisplayRole):
        if role != QtCore.Qt.DisplayRole:
            return QtCore.QVariant()

        if not index.isValid():
            return QtCore.QVariant()

        return QtCore.QVariant(str(self._df.iloc[index.row(), index.column()]))

    def setData(self, index, value, role):
        row = self._df.index[index.row()]
        col = self._df.columns[index.column()]
        if hasattr(value, 'toPyObject'):
            value = value.toPyObject()
        else:
            dtype = self._df[col].dtype
        if dtype != object:
            value = None if value == '' else dtype.type(value)
        self._df.set_value(row, col, value)
        return True

    def rowCount(self, parent=QtCore.QModelIndex()): 
        return len(self._df.index)

    def columnCount(self, parent=QtCore.QModelIndex()): 
        return len(self._df.columns)

    def sort(self, column, order):
        colname = self._df.columns.tolist()[column]
        self.layoutAboutToBeChanged.emit()
        self._df.sort_values(colname, ascending= order == QtCore.Qt.AscendingOrder, inplace=True)
        self._df.reset_index(inplace=True, drop=True)
        self.layoutChanged.emit()


if __name__ == '__main__':
    app = QtWidgets.QApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)
    else:
        print('QApplication instance already exists: %s' % str(app))
    main = MyWindowClass(None)
    main.show()

    sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:0)

最好不要创建带有永久打开编辑器的委托,因为它可以访问QModelIndex,另一方面,将添加具有标题数据的行。最后使用_df来获取熊猫。

#include <iostream>
using namespace std;

int main()
{

    int m[24][24], i, j, k = 0;
    int linia, coloana, piesa, lac=0;
    int mutari = 0;
    int ceva;
    cout << "Cate linii si cate coloane ? :";
    cin >> lac;
    ceva = lac;

    if (lac>1 && lac<25) {
        for (i = 0; i < lac; i++)
        {
            for (j = 0; j < lac; j++)
            {

                m[i][0] = lac;
                m[i][1] = ceva-1;
                ceva = ceva;

                m[i][j] = ceva - 1;
                ceva = ceva;

                if (i == j) {
                    m[i][j] = 2;
                    m[1][1] = 2;
                }
            };              
        };

        for (i = 0; i < lac; i++)
        {
            for (j = 0; j < lac; j++)
            {
                cout << m[i][j] << " ";
            }
            cout << endl;
        }
    }

    else cout << "Numarul de linii si coloane trebuie sa fie >=2 si <= 24" << endl;
    return 0;
}