Показать строковые значения по оси x в pyqtgraph

Я хочу отображать строковые значения для тиков по оси X в pyqtgraph. Сейчас я не могу понять, как это сделать.

Ex:

x = ['a', 'b', 'c', 'd', 'e', 'f']
y = [1, 2, 3, 4, ,5, 6]
pg.plot(x, y) 

Когда я пытаюсь передать массив строк в переменную x, он пытается преобразовать его в число с плавающей запятой и ломает графический интерфейс с сообщением об ошибке.


person coder006    schedule 02.08.2015    source источник


Ответы (2)


Обычно в pyqtgraph при работе с пользовательскими строками осей люди подклассируют AxisItem и переопределяют tickStrings со строками, которые они хотят отобразить.

См., например. pyqtgraph: как отображать время серии (дата и время по оси x)?

Pyqtgraphs axisitem также имеет встроенный setTicks который позволяет указать галочки, которые будут отображаться, это можно сделать для такой простой проблемы, как эта, вместо создания подкласса AxisItem.


Построение с пользовательской строкой по оси x может быть выполнено следующим образом.

  • Создайте словарь со значениями x вместе со строками, которые будут отображаться на оси.

xdict = {0:'a', 1:'b', 2:'c', 3:'d', 4:'e', 5:'f'}

или с помощью

x = ['a', 'b', 'c', 'd', 'e', 'f']
xdict = dict(enumerate(x))
  • Используйте setTicks в AxisItem или Подкласс AxisItem и в tickStrings найдите строку, соответствующую значению.

1. Использование стандартного pyqtgraph AxisItem и setTicks

    from PyQt4 import QtCore
    import pyqtgraph as pg

    x = ['a', 'b', 'c', 'd', 'e', 'f']
    y = [1, 2, 3, 4, 5, 6]
    xdict = dict(enumerate(x))

    win = pg.GraphicsWindow()
    stringaxis = pg.AxisItem(orientation='bottom')
    stringaxis.setTicks([xdict.items()])
    plot = win.addPlot(axisItems={'bottom': stringaxis})
    curve = plot.plot(list(xdict.keys()),y)

    if __name__ == '__main__':
        import sys
        if sys.flags.interactive != 1 or not hasattr(QtCore, 'PYQT_VERSION'):
            pg.QtGui.QApplication.exec_()

2. Реализация путем создания подкласса AxisItem

Это более общий метод, который можно легко изменить на всевозможные забавные вещи, например. преобразование временной метки unix в дату.

    from PyQt4 import QtCore
    import pyqtgraph as pg
    import numpy as np

    class MyStringAxis(pg.AxisItem):
        def __init__(self, xdict, *args, **kwargs):
            pg.AxisItem.__init__(self, *args, **kwargs)
            self.x_values = np.asarray(xdict.keys())
            self.x_strings = xdict.values()

        def tickStrings(self, values, scale, spacing):
            strings = []
            for v in values:
                # vs is the original tick value
                vs = v * scale
                # if we have vs in our values, show the string
                # otherwise show nothing
                if vs in self.x_values:
                    # Find the string with x_values closest to vs
                    vstr = self.x_strings[np.abs(self.x_values-vs).argmin()]
                else:
                    vstr = ""
                strings.append(vstr)
            return strings

    x = ['a', 'b', 'c', 'd', 'e', 'f']
    y = [1, 2, 3, 4, 5, 6]
    xdict = dict(enumerate(x))

    win = pg.GraphicsWindow()
    stringaxis = MyStringAxis(xdict, orientation='bottom')
    plot = win.addPlot(axisItems={'bottom': stringaxis})
    curve = plot.plot(list(xdict.keys()),y)

    if __name__ == '__main__':
        import sys
        if sys.flags.interactive != 1 or not hasattr(QtCore, 'PYQT_VERSION'):
            pg.QtGui.QApplication.exec_()

Скриншот из примера: Скриншот из примера

person luddek    schedule 14.08.2015
comment
Хорошая работа. Как лучший способ создать xdict вы можете использовать enumerate : xdict = dict(enumerate(x)) - person kasravnd; 19.01.2016
comment
Вы также можете избавить себя от хлопотного набора текста, используя x = 'abcdef' вместо x = ['a', 'b', 'c', 'd', 'e', 'f']. - person jacg; 01.11.2016

Я считаю, что проще всего подготовить список индексов и список ваших строк, а затем zip их вместе:

ticks = [list(zip(range(5), ('a', 'b', 'c', 'd', 'e')))]

Вы можете получить существующий AxisItem PlotWidget следующим образом:

pw = pg.PlotWidget()
xax = pw.getAxis('bottom')

И, наконец, установите галочки оси так:

xax.setTicks(ticks)

Насколько я могу судить, PlotWidgets автоматически включает «нижний» и «левый» AxisItems, но вы можете создавать и добавлять другие, если хотите.

person pattivacek    schedule 31.01.2017