2017-08-09 79 views
1

首先,我對堆棧溢出和整體編碼比較陌生,請讓我知道我將來如何改進我的帖子。我目前正在研究一個應用程序,該應用程序將讀取帶有可變列數和範圍的表格數據(本例中爲CSV),並將所有列繪製到帶有嵌入式matplotlib的PyQt5 GUI畫布中。我們的目標是通過點擊某些東西來隱藏/顯示各個列,以便快速進行數據比較。在我的情況下,我已經通過連接圖例項目點擊事件並通過減少阿爾法來將繪圖設置爲不可見來完成。在隱藏/顯示列時在Matplotlib中調整軸的大小

這裏的數據的珍聞我讀:

​​

而且我的代碼:

enter image description here

import pandas as pd 
from PyQt5.QtCore import * 
from PyQt5 import QtGui 
from PyQt5.QtCore import pyqtSignal 
from PyQt5.QtWidgets import QApplication, QLabel, QDialog, QLineEdit, QVBoxLayout, QComboBox, QStyleOptionComboBox, QSpinBox, QDoubleSpinBox, QGridLayout, QPushButton 
from math import * 
import matplotlib.pyplot as plt 
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas 
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar 
import datetime 
import sys 


def main(): 

#Read in CSV dataset as Pandas dataframe and set index to column 0 
    df = pd.read_csv('dataset.csv', index_col=0) 

    #Get the count of columns in the csv file and save the headers as a list 
    col_count = len(df.columns) 
    col_headers = list(df) 


    df['A'] = df['A']*1000 

#Form class for displaying the GUI 
    class Form(QDialog): 

     def __init__(self, parent=None, width=400, height=400): 
      super(Form, self).__init__(parent) 

      #Create the figure and canvas for the plot 
      self.figure = plt.figure(figsize=(width, height)) 
      self.canvas = FigureCanvas(self.figure) 
      self.setWindowTitle("Stock Prices 1990 - 2012") 

      #Create Navigation Toolbar (Possibly remove this if adding overhead and no functionality) 
      self.navBar = NavigationToolbar(self.canvas, self) 

      #Add Widgets to layout 
      layout = QGridLayout() 
      layout.addWidget(self.canvas, 2, 0) 
      layout.addWidget(self.navBar, 0, 0) 

      #Apply layout settings 
      self.setLayout(layout) 

      #Connect the pick event on the canvas to the onpick method 
      self.canvas.mpl_connect('pick_event', self.onpick) 

      # Add the dict as a class method so it can be passed 
      self.lined = dict() 

     def plot(self): 
      #Create Plots and set axis labels 
      plt.cla() 
      ax = self.figure.add_subplot(111) 
      ax.set_xlabel('Date') 
      ax.set_ylabel('Price') 

      #Empty list to hold the tuples of lines plotted 
      lines = [] 

      #Set variables for each column in pandas dataframe 
      for i in range(col_count): 
       x, = ax.plot(pd.to_datetime(df.index), df[col_headers[i]], label=col_headers[i]) 
       lines.append(x) 

      # Create legend from label properties 
      leg = ax.legend(loc='upper left', fancybox=True, shadow=True) 
      leg.get_frame().set_alpha(0.4) 

      for legline, origline in zip(leg.get_lines(), lines): 
       legline.set_picker(5) # 5 pts tolerance 
       self.lined[legline] = origline 

      ax.autoscale(True, axis='y') 

      #Draw canvas 
      self.canvas.draw() 

     def onpick(self, event): 
      # on the pick event, find the orig line corresponding to the 
      # legend proxy line, and toggle the visibility 
      legline = event.artist 
      origline = self.lined[legline] 
      vis = not origline.get_visible() 
      origline.set_visible(vis) 
      # Change the alpha on the line in the legend so we can see what lines 
      # have been toggled 
      if vis: 
       legline.set_alpha(1.0) 
      else: 
       legline.set_alpha(0.2) 

      self.canvas.draw() 

    app = QApplication(sys.argv) 
    form = Form() 
    form.show() 
    form.plot() 
    app.exec_() 

if __name__ == '__main__': 
    main() 

圖工作的圖片

這部分是所有工作wonde rfully。現在的問題是,我希望劇情重新調整以適應目前可見的任何情況。例如,如果我的列(y軸)包含10,000-11,000範圍內的數據,並且我隱藏該軸並顯示範圍爲10-20的繪圖,我希望Y軸重新縮放以適合當前顯示的數據集。所以理想情況下,當我點擊圖例時,我希望看到圖形嘗試適合當前數據集。顯然,在極其不同的範圍內並排比較數據集仍然無法正常工作,但我希望能夠在同一個圖中查看類似的數據範圍,並在更改爲具有不同範圍的數據集時自動切換。我試圖啓用自動縮放,但我猜測,因爲我只是將alpha縮小到不可見,它不是縮放,因爲繪圖仍處於活動狀態。我不確定我是否應該尋找一種方法來實際移除繪圖並重新繪製畫布,或者也可以將縮放合併到當前隱藏/顯示列的方法中。任何建議將不勝感激。

+0

至於什麼改善你的問題:不要只花半個句子的實際問題。 *「我希望情節重新規模以適應目前可見的任何情況」*不足以理解問題。 – ImportanceOfBeingErnest

+0

好注意;謝謝。不知道我在發佈之前沒有在評論中看到這一點。 –

回答

1

爲了更新軸的限制之一可以使用

ax.relim() 
ax.autoscale_view() 

然而,你是完全正確的:只要一條線是在軸線,無論是可見光還是不,軸限制不會更改。
解決方案可能是從軸(line.remove())中刪除相關線路,並在點擊圖例(ax.add_line(line))後再次添加。在這種情況下,仍然可以使用該線的可見性作爲標記,以確定在發生點擊事件時是否應添加或刪除該線。

一個完整的例子,基於matplotlib legend picker的代碼(因爲問題中的QT部分在這裏似乎沒有關係)。

import numpy as np 
import matplotlib.pyplot as plt 

t = np.linspace(0.0, 1.5) 
y1 = 2*np.sin(np.pi*t) 
y2 = 4*np.sin(np.pi*2*t) 

fig, ax = plt.subplots() 
ax.set_title('Click on legend line to toggle line on/off') 
line1, = ax.plot(t, y1, lw=2, color='red', label='1 HZ') 
line2, = ax.plot(t, y2, lw=2, color='blue', label='2 HZ') 
leg = ax.legend(loc='upper left', fancybox=True, shadow=True) 
leg.get_frame().set_alpha(0.4) 

lines = [line1, line2] 
lined = dict() 
for legline, origline in zip(leg.get_lines(), lines): 
    legline.set_picker(5) 
    lined[legline] = origline 


def onpick(event): 
    legline = event.artist 
    origline = lined[legline] 

    vis = not origline.get_visible() 
    origline.set_visible(vis) 

    # if line is made invisible, also remove it from axes 
    # if line is made visible again, add it to axes again 
    if not vis: 
     origline.remove() 
    else: 
     ax.add_line(origline) 
    # in any case relimit the axes 
    ax.relim() 
    ax.autoscale_view() 

    if vis: 
     legline.set_alpha(1.0) 
    else: 
     legline.set_alpha(0.2) 

    fig.canvas.draw_idle() 

fig.canvas.mpl_connect('pick_event', onpick) 

plt.show() 
+0

奇妙的作品,非常感謝。 –

相關問題