def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()
        pgdf = PandasGuiDataFrame.cast(pgdf)
        pgdf.filter_viewer = self
        self.pgdf = pgdf

        self.list_view = self.ListView()
        self.list_model = self.ListModel(pgdf)
        self.list_view.setModel(self.list_model)

        self.text_input = QtWidgets.QLineEdit()
        self.text_input.setPlaceholderText("Enter query expression")
        self.text_input_label = QtWidgets.QLabel(
            '''<a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.query.html">What's a query expression?</a>'''
        )
        self.text_input_label.linkActivated.connect(
            lambda link: QDesktopServices.openUrl(QUrl(link)))
        self.text_input.setValidator(None)

        self.submit_button = QtWidgets.QPushButton("Add Filter")

        # Signals
        self.text_input.returnPressed.connect(self.add_filter)
        self.submit_button.clicked.connect(self.add_filter)

        # Layout
        self.new_filter_layout = QtWidgets.QHBoxLayout()
        self.new_filter_layout.addWidget(self.text_input)
        self.new_filter_layout.addWidget(self.submit_button)
        self.layout = QtWidgets.QVBoxLayout()
        self.layout.addLayout(self.new_filter_layout)
        self.layout.addWidget(self.text_input_label)
        self.layout.addWidget(self.list_view)
        self.setLayout(self.layout)
    def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()

        pgdf = PandasGuiDataFrame.cast(pgdf)
        pgdf.dataframe_explorer = self
        self.pgdf = pgdf

        # Dock setup
        self.docks: List[DockWidget] = []
        self.setDockOptions(self.GroupedDragging | self.AllowTabbedDocks | self.AllowNestedDocks)
        self.setTabPosition(Qt.AllDockWidgetAreas, QtWidgets.QTabWidget.North)

        # DataFrame tab
        self.dataframe_tab = DataFrameViewer(pgdf)
        self.dataframe_dock = self.add_view(self.dataframe_tab, "DataFrame")

        # Filters tab
        self.filters_tab = FilterViewer(pgdf)
        self.filters_dock = self.add_view(self.filters_tab, "Filters")

        # Statistics tab
        self.statistics_tab = self.make_statistics_tab(pgdf)
        self.statistics_dock = self.add_view(self.statistics_tab, "Statistics")

        # Grapher tab
        self.grapher_tab = Grapher(pgdf)
        self.grapher_dock = self.add_view(self.grapher_tab, "Grapher")

        # Layout
        self.dataframe_tab.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
Exemple #3
0
    def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()

        self.pgdf = PandasGuiDataFrame.cast(pgdf)

        self.setWindowTitle("Graph Builder")
        self.workers = []
        self.current_worker = None

        # Dropdown to select plot type
        self.plot_type_picker = QtWidgets.QListWidget()
        self.plot_type_picker.setViewMode(self.plot_type_picker.IconMode)
        self.plot_type_picker.setWordWrap(True)
        self.plot_type_picker.setSpacing(20)
        self.plot_type_picker.setResizeMode(self.plot_type_picker.Adjust)
        self.plot_type_picker.setDragDropMode(self.plot_type_picker.NoDragDrop)


        self.plot_type_picker.sizeHint = lambda: QtCore.QSize(500, 250)

        for schema in schemas:
            icon = QtGui.QIcon(schema.icon_path)
            text = schema.label
            item = QtWidgets.QListWidgetItem(icon, text)
            self.plot_type_picker.addItem(item)

        # UI setup
        self.figure_viewer = PlotlyViewer()
        self.figure_viewer.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                         QtWidgets.QSizePolicy.Expanding)

        df = flatten_df(self.pgdf.dataframe)
        self.dragger = Dragger(sources=df.columns, destinations=[],
                               source_types=df.dtypes.values.astype(str))

        self.spinner = Spinner()
        self.spinner.setParent(self.figure_viewer)

        self.layout = QtWidgets.QGridLayout()
        self.layout.addWidget(self.plot_type_picker, 0, 0)
        self.layout.addWidget(self.dragger, 1, 0)
        self.layout.addWidget(self.figure_viewer, 0, 1, 2, 1)
        self.layout.setColumnStretch(0, 0)
        self.layout.setColumnStretch(1, 1)
        self.dragger.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self.plot_type_picker.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)

        self.setLayout(self.layout)

        # Signals
        self.plot_type_picker.itemSelectionChanged.connect(self.on_type_changed)
        self.dragger.finished.connect(self.on_dragger_finished)

        # Initial selection
        self.plot_type_picker.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.plot_type_picker.setCurrentRow(0)
        self.on_type_changed()

        # Show a blank axis initially
        self.figure_viewer.set_figure(plotly.graph_objs.Figure())
Exemple #4
0
    def add_df(self, df: pd.DataFrame, name: str):
        """
        Add a new DataFrame to the GUI
        """
        pgdf = PandasGuiDataFrame.cast(df)
        pgdf.name = name
        self.store.add_pgdf(pgdf)

        dfe = DataFrameExplorer(pgdf)
        self.stacked_widget.addWidget(dfe)

        self.add_df_to_nav(name)
Exemple #5
0
    def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()

        self.pgdf = PandasGuiDataFrame.cast(pgdf)

        self.prev_kwargs = ({})  # This is for carrying plot arg selections forward to new plot types

        self.setWindowTitle("Graph Builder")
        self.workers = []
        self.current_worker = None

        # Dropdown to select plot type
        self.plot_type_picker = QtWidgets.QListWidget()

        for schema in schemas:
            icon = QtGui.QIcon(schema.icon_path)
            text = schema.label
            item = QtWidgets.QListWidgetItem(icon, text)
            self.plot_type_picker.addItem(item)

        # UI setup
        self.figure_viewer = PlotlyViewer()
        self.figure_viewer.setSizePolicy(QtWidgets.QSizePolicy.Expanding,
                                         QtWidgets.QSizePolicy.Expanding)

        df = self.get_df()
        self.dragger = Dragger(sources=df.columns, destinations=[],
                               source_types=df.dtypes.values.astype(str))

        self.spinner = Spinner()
        self.spinner.setParent(self.figure_viewer)

        self.layout = QtWidgets.QGridLayout()
        self.layout.addWidget(self.plot_type_picker, 0, 0)
        self.layout.addWidget(self.dragger, 1, 0)
        self.layout.addWidget(self.figure_viewer, 0, 1, 2, 1)
        self.layout.setColumnStretch(0, 0)
        self.layout.setColumnStretch(1, 1)

        self.setLayout(self.layout)

        # Signals
        self.plot_type_picker.itemSelectionChanged.connect(self.update_dragger)
        self.dragger.finished.connect(self.update_plot)

        # Initial selection
        self.plot_type_picker.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.plot_type_picker.setCurrentRow(0)
        self.update_dragger()

        # Show a blank axis initially
        self.figure_viewer.set_figure(px.scatter())
    def make_statistics_tab(self, pgdf: PandasGuiDataFrame):
        stats_df = pd.DataFrame(
            {
                "Type": pgdf.dataframe.dtypes.replace("object", "string").astype(str),
                "Count": pgdf.dataframe.count(),
                "N Unique": pgdf.dataframe.nunique(),
                "Mean": pgdf.dataframe.mean(numeric_only=True),
                "StdDev": pgdf.dataframe.std(numeric_only=True),
                "Min": pgdf.dataframe.min(numeric_only=True),
                "Max": pgdf.dataframe.max(numeric_only=True),
            }
        )

        stats_pgdf = PandasGuiDataFrame(stats_df.reset_index())
        w = DataFrameViewer(stats_pgdf)
        w.setAutoFillBackground(True)
        return w
Exemple #7
0
    def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()

        self.pgdf = PandasGuiDataFrame.cast(pgdf)

        self.setWindowTitle("Reshaper")

        # Dropdown to select reshape type
        self.reshape_type_picker = QtWidgets.QListWidget()
        self.reshape_type_picker.setViewMode(self.reshape_type_picker.IconMode)
        self.reshape_type_picker.setWordWrap(True)
        self.reshape_type_picker.setSpacing(20)
        self.reshape_type_picker.setResizeMode(self.reshape_type_picker.Adjust)
        self.reshape_type_picker.setDragDropMode(self.reshape_type_picker.NoDragDrop)

        for schema in schemas:
            icon = QtGui.QIcon(schema.icon_path)
            text = schema.label
            item = QtWidgets.QListWidgetItem(icon, text)
            self.reshape_type_picker.addItem(item)

        df = flatten_df(self.pgdf.dataframe)
        self.dragger = Dragger(sources=df.columns, destinations=[],
                               source_types=df.dtypes.values.astype(str))

        self.layout = QtWidgets.QGridLayout()
        self.layout.addWidget(self.reshape_type_picker, 0, 0)
        self.layout.addWidget(self.dragger, 1, 0)
        self.layout.setColumnStretch(0, 0)
        self.layout.setColumnStretch(1, 1)
        self.dragger.setSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        self.reshape_type_picker.setSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Preferred)

        self.setLayout(self.layout)

        # Signals
        self.reshape_type_picker.itemSelectionChanged.connect(self.on_type_changed)
        self.dragger.finished.connect(self.on_dragger_finished)

        # Initial selection
        self.reshape_type_picker.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
        self.reshape_type_picker.setCurrentRow(0)
        self.on_type_changed()
    def __init__(self, pgdf: PandasGuiDataFrame):
        super().__init__()

        pgdf = PandasGuiDataFrame.cast(pgdf)
        pgdf.dataframe_viewer = self

        self.pgdf = pgdf

        # Indicates whether the widget has been shown yet. Set to True in
        self._loaded = False

        # Set up DataFrame TableView and Model
        self.dataView = DataTableView(parent=self)

        # Create headers
        self.columnHeader = HeaderView(parent=self, orientation=Qt.Horizontal)
        self.indexHeader = HeaderView(parent=self, orientation=Qt.Vertical)

        self.columnHeaderNames = HeaderNamesView(parent=self, orientation=Qt.Horizontal)
        self.indexHeaderNames = HeaderNamesView(parent=self, orientation=Qt.Vertical)

        # Set up layout
        self.gridLayout = QtWidgets.QGridLayout()
        self.setLayout(self.gridLayout)

        # Link scrollbars
        # Scrolling in data table also scrolls the headers
        self.dataView.horizontalScrollBar().valueChanged.connect(
            self.columnHeader.horizontalScrollBar().setValue
        )
        self.dataView.verticalScrollBar().valueChanged.connect(
            self.indexHeader.verticalScrollBar().setValue
        )
        # Scrolling in headers also scrolls the data table
        self.columnHeader.horizontalScrollBar().valueChanged.connect(
            self.dataView.horizontalScrollBar().setValue
        )
        self.indexHeader.verticalScrollBar().valueChanged.connect(
            self.dataView.verticalScrollBar().setValue
        )

        self.dataView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.dataView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)

        # Disable scrolling on the headers. Even though the scrollbars are hidden, scrolling by dragging desyncs them
        self.indexHeader.horizontalScrollBar().valueChanged.connect(lambda: None)

        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setSpacing(0)

        # Add items to 4x4 grid layout
        self.gridLayout.addWidget(self.columnHeader, 0, 1, 1, 2)
        self.gridLayout.addWidget(self.indexHeader, 1, 0, 2, 2)
        self.gridLayout.addWidget(self.dataView, 2, 2, 1, 1)
        self.gridLayout.addWidget(self.dataView.horizontalScrollBar(), 3, 2, 1, 1)
        self.gridLayout.addWidget(self.dataView.verticalScrollBar(), 2, 3, 1, 1)
        self.gridLayout.addWidget(self.columnHeaderNames, 0, 3, 1, 1)
        self.gridLayout.addWidget(self.indexHeaderNames, 0, 0, 1, 1, Qt.AlignBottom)

        # These expand when the window is enlarged instead of having the grid squares spread out
        self.gridLayout.setColumnStretch(4, 1)
        self.gridLayout.setRowStretch(4, 1)

        self.gridLayout.addItem(
            QtWidgets.QSpacerItem(0, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding), 0, 0, 1, 1, )

        # Do this at top so sizeHints are calculated correctly
        self.set_styles()
        self.updateGeometry()
                    | QtCore.Qt.ItemIsSelectable
                    | QtCore.Qt.ItemIsUserCheckable)

        def setData(self, index, value, role=QtCore.Qt.DisplayRole):
            row = index.row()
            if role == Qt.CheckStateRole:
                self.pgdf.toggle_filter(row)
                return True

            if role == QtCore.Qt.EditRole:
                self.pgdf.edit_filter(row, value)
                return True

            return False


if __name__ == "__main__":
    # Create a QtWidgets.QApplication instance or use the existing one if it exists
    app = QtWidgets.QApplication(sys.argv)
    from pandasgui.datasets import pokemon

    stacked_widget = QtWidgets.QStackedWidget()
    pokemon = PandasGuiDataFrame(pokemon)
    pokemon.add_filter('Generation > 3', enabled=False)
    pokemon.add_filter('Attack > 50', enabled=True)
    pokemon.add_filter('Defense < 30', enabled=True)
    fv = FilterViewer(pokemon)
    stacked_widget.addWidget(fv)
    stacked_widget.show()
    app.exec_()