質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.40%

  • Python

    12808questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 3.x

    10698questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Qt

    212questions

    QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。

PyQt5で複数の座標をプロットしたい

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 736

Ykkykk

score 85

 前提・実現したいこと

PyQt5を使用して座標をプロットしてみたいと思っております。CSVファイルに格納された値を取り出し、それを座標として点々を打っていくイメージです。例えば、A列の値をX座標、B列の値をY座標とするような感じです。
PyQt5でCSVファイルをインポートし、Pandasで値を読み取り、プロットした結果をウィンドウに表示したいです。

 発生している問題・エラーメッセージ

ウィジェットとして作成した表示領域の上に、どのように座標をプロットしていくのかがわかりません。
以下のコードですと、表示領域とボタンは表示できているのですが、罫線が表示されません。
また、CsvPlotterの中でreadCsv()関数を定義しPandasを使用しようとしているのですが、ここで使用すると、MapPlotの方でプロットする点を生成できなくなるような気もしています。一方で、CsvPlotterの方では、ファイルをインポートするためにreadCsv()関数を定義する必要があるようにも思い、どうしたらいいのかわかりません。

 該当のソースコード

# - * - coding: utf-8 - * -

import sys

import pandas as pd

from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *

class CsvPlotter(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):

        maxWidth = self.maximumWidth()
        maxHeight = self.maximumHeight()

        self.setLayout()
        self.statusBar()

        self.setGeometry(0, 0, maxWidth, maxHeight)
        self.setWindowTitle('Csv Plotter')

        self.show()

    def setLayout(self):

        exitAction = QAction('&exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit Application.')
        exitAction.triggered.connect(qApp.quit)

        readCsvAction = QAction('&Open CSV', self)
        readCsvAction.setStatusTip('Open CSV File.')
        readCsvAction.triggered.connect(self.readCsv)

        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)
        fileMenu.addAction(readCsvAction)

        self.w = QWidget()

        self.paint_area = QGraphicsView()
        scene = QGraphicsScene(self.paint_area)
        srect = self.paint_area.rect()
        width = srect.width()
        height = srect.height()

        self.open_file_button = QPushButton('Open File', self)
        self.open_file_button.clicked.connect(self.readCsv)

        w_layout = QGridLayout()

        w_layout.addWidget(self.paint_area, 0, 0, 36, 3)

        w_layout.addWidget(self.open_file_button, 1, 11, 1,1)
        self.w.setLayout(main_pane)
        self.setCentralWidget(self.w)


    def readCsv(self):
        path = QFileDialog.getOpenFileName(self, 'Open a file.','~')
        self.df = pd.read_csv(path, header=None)

class MapPlot(QGraphicsItem):

    def __init__(self, width=400, height=400):
        super(MapPlot, self).__init__()

        self.width = width
        self.height = height
        self.x_origin = width * 1 / 2
        self.y_origin = height * 1 / 2

    def paint(self, painter, option, widget):
        painter.setPen(Qt.gray)
        painter.drawLine(0, self.y_origin, self.width, self.y_origin)
        painter.drawLine(self.x_origin, 0, self.x_origin, self.height)

def main():
        app = QApplication(sys.argv)
        gui = CsvPlotter()
        sys.exit(app.exec_())

if __name__ == '__main__':
    main()

質問自体がわかりにくいかと思いますが、ご助言いただけますと幸いです。
よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

 グラフの描写

Qt 機能でも点を描画したりはできますが、それで体裁の整ったグラフを作成するのは大変です。
matplotlib などの Python のグラフ作成ライブラリでグラフを作成し、画像化して Qt 上に表示するのがよいかと思います。

 グラフ作成の手順

  • 自分は pandas に詳しくないので、matplotlib でグラフを作成しました。
  • 画像を表示するだけなので、QLabel を使用しました。
  1. numpy で CSV を読み込む。
  2. matplotlib でグラフをレンダリングする。
  3. 作成した画像を QImage に変換する。

イメージ説明

 サンプルコード

サンプルとして、以下の CSV を使いました。

X,Y
-0.11904244125880663,0.38604683228846814
-1.057116895394611,-1.637295904162237
-1.6226321873996457,-0.8903071233344362
0.31579843377941075,-1.2160738373532796
-1.6004130434344865,-0.011108237917387532
-2.0392655019956885,1.1976755572381765
-1.1269736514295516,-0.5372561852679467
1.2759382926636726,-0.20616965560956768
-0.936968605825384,0.2800013518075348
0.8548796880555768,0.16609017856128488
0.14483257755905343,1.2362537405002108
-0.38195509077267725,-1.2488842012333055
0.7061953129595218,-0.41066161883676366
-1.8833232284258883,-0.2668120276323988
-1.027057833849912,0.5221427636845989
1.123321837354084,1.4793126503521312
-0.7427780969460384,0.14812511748813958
0.7513514254097702,-0.28033732779987636
-2.1179155424676614,0.5668258470393494
-0.48140251707086207,0.12088514237687714
# - * - coding: utf-8 - * -

import sys

import matplotlib
matplotlib.use('Agg')  # Agg バックエンドを使用
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_agg import FigureCanvasAgg
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *


class CsvPlotter(QMainWindow):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.setLayout()
        self.statusBar()

        self.setGeometry(0, 0, 600, 600)
        self.setWindowTitle('Csv Plotter')

    def setLayout(self):
        # 「アプリケーションを閉じる」アクションを作成する。
        exitAction = QAction('&exit', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit Application.')
        exitAction.triggered.connect(qApp.quit)

        # 「CSV ファイルを開く」アクションを作成する。
        readCsvAction = QAction('&Open CSV', self)
        readCsvAction.setStatusTip('Open CSV File.')
        readCsvAction.triggered.connect(self.readCsv)

        # メニューバーに設定する。
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('&File')
        fileMenu.addAction(exitAction)
        fileMenu.addAction(readCsvAction)

        # 「CSV ファイルを開く」ボタンを作成する。
        open_file_button = QPushButton('Open File', self)
        open_file_button.clicked.connect(self.readCsv)

        self.view = QLabel()
        # 画像に合わせて QLabel の大きさを変更する。
        self.view.setScaledContents(True)

        # レイアウトを設定する。
        w_layout = QGridLayout()
        w_layout.addWidget(self.view, 0, 0, 36, 3)
        w_layout.addWidget(open_file_button, 1, 11, 1, 1)
        self.w = QWidget()
        self.w.setLayout(w_layout)
        self.setCentralWidget(self.w)

    def readCsv(self):
        path = QFileDialog.getOpenFileName(self, 'Open a file.', '~')
        if not path[0]:
            return  # ファイルが選択されていない場合

        # CSV を読み込む。
        data = np.loadtxt(path[0], delimiter=",", skiprows=1)

        # グラフを作成する。
        pixmap = self.create_graph(data)

        # ラベルに画像を表示する。
        self.view.setPixmap(pixmap)

    def create_graph(self, data):
        # 散布図を作成する。
        fig, axes = plt.subplots(figsize=(5, 5))
        axes.scatter(data[:, 0], data[:, 1])

        # レンダリングする。
        canvas = FigureCanvasAgg(fig)
        canvas.draw()

        # matplotlib がレンダリングした画像を QImage に変換する。
        w, h = canvas.get_width_height()
        image = QImage(
            canvas.buffer_rgba(), w, h, QImage.Format_ARGB32)
        return QPixmap(image)


def main():
    app = QApplication(sys.argv)
    gui = CsvPlotter()
    gui.show()
    sys.exit(app.exec_())


if __name__ == '__main__':
    main()

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/12 12:07

    ご回答いただきありがとうございます。
    matplotlibを使用した方がグラフを書きやすいのですね。
    ただ、質問が足りなかったのですが、CSVファイルに入っている座標は地理的な緯度経度の座標で、それを座標平面上にプロットしたいと考えております。特にグーグルマップのような地理的な図像は不要で、単純にX軸とY軸のある座標平面上に地理的な緯度経度の座標をプロットすることはできないかな、と考えています。
    何はともあれ、ご回答いただきありがとうございました!!

    キャンセル

  • 2018/09/12 12:24

    matplotlib では、xy軸のラベルを数値でなく緯度経度に変更したり、座標軸を直交座標でなく、ハンメル図法に変えたりもできますが、それではダメなのでしょうか?
    各点に緯度経度のテキストをつけることももちろんできます。

    https://scitools.org.uk/cartopy/docs/v0.13/matplotlib/gridliner.html
    https://matplotlib.org/gallery/misc/custom_projection.html

    キャンセル

  • 2018/09/12 12:31

    そうなんですね!!!!
    初めて知りました。参考にさせていただきます。本当にありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.40%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Python

    12808questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • Python 3.x

    10698questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • Qt

    212questions

    QtはGUIプログラムの開発で広く使われているクロスプラットフォーム開発のフレームワークです。