Рисование точек на AxisItem - PyQtGraph - PullRequest
0 голосов
/ 14 июля 2020

Я пытаюсь создать графики параллельных координат с помощью PyQtGraph. У меня есть два возможных подхода: либо несколько элементов PlotItem рядом, либо несколько ViewBox (например, MultiplePlotAxes.py, пример ). В любом случае точки должны быть нарисованы на AxisItems, а не рядом (затем вручную нарисованы линии для соединения точек).

Я собрал (очень грубый) пример того, что я зашло так далеко. Для каждой оси точки нанесены при x = 0. Они нарисованы рядом с осью y. Вы можете щелкнуть и перетащить точки ближе к оси, но они начинают исчезать при перетаскивании на нее.

from pyqtgraph.Qt import QtGui, QtCore
from pyqtgraph import PlotWidget, PlotItem, PlotDataItem, AxisItem
import numpy as np
import pandas as pd

class ParallelCoordinatePlotObject(QtGui.QWidget):
    def __init__(self, df, style, key):
        super().__init__()
        
        self.layout = QtGui.QHBoxLayout()
        self.setLayout(self.layout)
        self.layout.setContentsMargins(1,1,1,1)
        self.layout.setSpacing(0)
        self.setContentsMargins(1,1,1,1)
        
        # list of axis names
        cols = list(df.columns)
        cols.remove(key)
        
        # data series names
        self.names = list(style.keys())
        
        self.makeAxes(cols)
        self.plotData(style)
        
    def makeAxes(self, cols):
        self.plotItems = {}
        for column in cols:
            pw = PlotWidget(background='#ffffff')
            item = pw.getPlotItem()
            item.setLabel('left', column)
            self.plotItems[column] = item
            item.hideAxis('bottom')
            self.layout.addWidget(pw)
            
    def plotData(self, style):
        for column, item in self.plotItems.items(): # for each axis
            for name in self.names: # for each data series
                points = np.array(df.query(f'Name=="{name}"')[column])
                x = np.zeros(len(points))
                data = np.stack([x, points], axis=-1)
                colour = style[name]['colour']
                symbol = style[name]['symbol']
                item.plot(data, pen=None, symbol=symbol, symbolPen=colour,
                          symbolBrush=None)


df = pd.read_csv('https://raw.githubusercontent.com/pandas-dev/pandas/master/pandas/tests/io/data/csv/iris.csv')
c = iter(['r', 'g', 'b'])
s = iter(['x', 'o', '+'])
style = {name:{'colour':next(c), 'symbol':next(s)} for name in set(df['Name'])}

app = QtGui.QApplication([])
mw = QtGui.QMainWindow()
mw.setWindowTitle('Parallel Coordinate Plot')
mw.resize(800,800)
mw.show()
cw = ParallelCoordinatePlotObject(df, style, key='Name')
mw.setCentralWidget(cw)

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == '__main__':
    import sys
    if (sys.flags.interactive != 1) or not hasattr(QtCore, 'PYQT_VERSION'):
        QtGui.QApplication.instance().exec_()

Я думаю, проблема может заключаться в том, что PlotItem добавляет оси и поле просмотра в QGraphicsGridLayout , поэтому элементы в окне просмотра не смогут перекрывать ось, поскольку они находятся в отдельных столбцах. Я попытался создать отдельные элементы AxisItems в makeAxes и добавить их с помощью PlotItem.addItem (это также потребовало переопределения AxisItem.setLogMode, поскольку PlotItem.addItem вызывает setLogMode данного элемента с двумя аргументы). Однако нарисованный AxisItem был огромным, серым, перевернутым и перевернутым.

Я использую PyQtGraph 0.11.0 и Python 3.6.2.

Любая помощь с был бы очень признателен :)

Потенциально полезная ссылка: лучшая Python реализация параллельных координатных графиков, которую я смог найти, была этот ответ , который использует twinx* 1027 matplotlib * метод создания осей, затем spine.set_position для их размещения, но я бы хотел иметь возможность использовать PyQtGraph, поскольку интерактивные возможности действительно полезны (а графики встраиваются в приложение PySide2) .

...