当サイトはアフィリエイトプログラムによる収益を得ています〈景品表示法に基づく表記です)

go(plotly.graph_objects)

【Plotlyで散布図】go.Scatterのグラフの描き方まとめ

2023年1月4日

これからPloltyで動くグラフを作りたい、もっとグラフをキレイに見せたい、後から簡単に見返せるグラフを作りたい。

そんな人はまずはPlotlyの基礎、goの散布図グラフgo.Scatterから始めてみよう。本記事ではgo.Scatterの使い方をざっくりと解説する。

本記事の内容は以下。

  • go.Scatterでグラフを作成
  • 点・線・文字をプロット点に設定
  • バブルチャートを作成
  • カラースケールの設定
  • マーカー、線の種類を変更
  • プロットを後から追加・更新
  • ホバーを設定
  • 大量のデータを軽く扱う

go.Scatterの基礎的な使い方が凝縮されているし、それぞれの変数の中身や仕組みが分かれば他のPlotlyのグラフ化にも応用できる。

是非とも頑張って読み進めてほしい。本記事のPython環境は以下。

  • Python 3.10.1
  • numpy 1.21.4
  • pandas 1.3.5
  • plotly 5.4.0
  • plotly-orca 3.4.2

参考になるサイト

Plotly公式

本記事のコード全文

下準備のimport

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio

まずは下準備としてのimport関連。今回は基本goを使用するが、一部データを作成・読み込みするためにnumpypandasを使用するのでimport

pioplotlyでのグラフ保存用のライブラリ。保存の仕方は色々あるがpioはその1つだ。

シンプルな1データのプロット


まずはシンプルにプロットする。ここでは変数plotに格納するなど処理を細かく分解しているが、いきなりgo.Figurego.Scatterを入れてもいい。

d = go.Scatter(
    x=(0, 1, 2),  # xの値
    y=(1, 3, 2),  # yの値
)

散布図はgo.Scatterで描画可能。引数はx, yでそれぞれ横軸と縦軸の値に相当する。その他にも引数は多くあるが、最低限はこれだけあればグラフは描ける。

プロットデータはgo.Scatterの状態ではなく、listなどの配列に入れる必要がある。ここでは変数plotがその役割を果たす。

# プロットはlistやtupleに入れないといけない
plot = [d]

プロットデータができるとそれをgo.Figureの引数dataに入れ、fig.showで表示。

途中のfig.update_layoutはフォントを大きくする設定。デフォルトだとフォントが小さく、記事に載せると見づらいから設定。後述する。

fig.update_layout(font_size=20, hoverlabel_font_size=20)

グラフの保存はhtml, png形式にしている。

import plotly.graph_objects as go
import plotly.io as pio

print('------------------------------------------------------------')
# シンプルにプロットしてみる

x = (0, 1, 2)
y = (1, 3, 2)

d = go.Scatter(
    x=x,  # xの値
    y=y,  # yの値
)
print(d)
# Scatter({
#     'x': [0, 1, 2], 'y': [1, 3, 2]
# })

# プロットはlistやtupleに入れないといけない
plot = [d]

# go.Figureでグラフ作成
fig = go.Figure(data=plot)  # plotは引数data
print(fig)
# Figure({
#     'data': [{'type': 'scatter', 'x': [0, 1, 2], 'y': [1, 3, 2]}], 'layout': {'template': '...'}
# })

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)

# グラフの表示
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'  # グラフ保存時の接頭辞
save_name = f"{prefix}_simple"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

複数データのプロット


複数プロットをする場合は、プロットデータをそれぞれgo.Scatterで作成する。今回だとy0, y1に対してそれぞれd0, d1を作成した。

あとは作成したd0, d1を配列としてplotに入れてgo.Figureでグラフを作成すればいい。

要するにやっていることはgo.Scatterを追加しただけ。なお、d1では引数でnameを追加し、プロットに名前をつけた。この時、名前をつけていないd0はデフォルトのtrace0になる。

import plotly.graph_objects as go
import plotly.io as pio

# 複数プロットは配列でまとめる

x = (0, 1, 2)
y0 = (1, 3, 2)
y1 = (2, 1, 3)

# 引数nameをプロットの名前をつけない場合は自動で「trace0」などの名称に
d0 = go.Scatter(
    x=x,  # xの値
    y=y0,  # y0の値
)

d1 = go.Scatter(
    x=x,  # xの値
    y=y1,  # y1の値
    name='y1'  # プロットの名前をy1に設定
)

# 複数プロットをまとまることも可能
plot = [d0, d1]

# go.Figureでグラフ作成
fig = go.Figure(data=plot)  # plotは引数data
print(fig)
# Figure({
#     'data': [{'type': 'scatter', 'x': [0, 1, 2], 'y': [1, 3, 2]},
#              {'name': 'y1', 'type': 'scatter', 'x': [0, 1, 2], 'y': [2, 1, 3]}],
#     'layout': {'template': '...'}
# })

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)

fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_multiple"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

go.Layoutでレイアウトを設定


散布図に限った話ではないが、plotlyのグラフでタイトルや軸ラベルを追加したい時にはレイアウトの設定が必要。こちらも色々な方法があるが、ここではplotと同じように変数layoutで独立させる方法をとる。

このグラフだと「グラフタイトル」と「横軸ラベル」を追加した。それぞれgo.Layoutの引数titleの中のtext, 引数xaxistitleを使う。引数がテレコなので注意。

layout = go.Layout(
    title=dict(text='TITLE'),
    xaxis=dict(title='X'),
)

layoutgo.Figureの中の引数dataと同じように引数layoutに入れると反映させることができる。

また、figを作成した後でもfig.update_layoutでレイアウト設定を追加することもできる。ここではフォントサイズの変更がこれに対応。

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)

データとタイトル・軸ラベルといったグラフの基本的な要素を使う際にはgo.Figureの引数datalayoutがあれば十分だ。

import plotly.graph_objects as go
import plotly.io as pio

# レイアウトの設定

x = (0, 1, 2)
y = (1, 3, 2)

plot = [go.Scatter(x=x, y=y)]

# レイアウトはgo.Layoutで設定可能
layout = go.Layout(
    title=dict(text='TITLE'),
    xaxis=dict(title='X'),
)
# レイアウトもgo.Figureに入れる
fig = go.Figure(data=plot, layout=layout)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_layout"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

modeでプロットの種類を変更


go.Scatterでは点だけや線と点など色々なパターンのプロットが可能。これらはgo.Scatterの引数modeで設定可能。modeでは以下の決まりがある。

  • ’lines’で線にする
  • ‘markers’で点にする
  • ‘text’でテキストにする
  • 上記をでつなげた組み合わせ
  • noenで非表示

詳しくはplotlyドキュメントを参照いただきたい。

今回のグラフでは合計8種類のグラフをyの値を変えながらプロットした。なおmode=’text’の際に表示するテキストは、go.Scatterの引数textで指定可能。ここではyの値にした。

また、noneにするとプロット点は非表示なるものの、マウスをかざすとちゃんとプロットされていることが確認できる。

import plotly.graph_objects as go
import plotly.io as pio

# 引数modeでプロットの種類を変更

# 引数modeでの組み合わせ
modes = [
    'lines', 'markers', 'text', 'none',
    'lines+markers', 'lines+text', 'markers+text',
    'lines+markers+text',
]

x = (0, 1, 2)
plot = []
for num, mode in enumerate(modes):  # forで全modeをプロット
    y = np.array((1, 3, 2)) + num  # 1プロットずつyの値を増やす
    d = go.Scatter(
        x=x, y=y,
        name=mode,  # プロットの名前はモードに
        mode=mode,  # プロットのモード
        text=y,  # modeにtextが入っている時用の表示テキストはyに
    )
    plot.append(d)

fig = go.Figure(data=plot)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_mode"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

textモードではtextpositionで位置を変えられる


go.Scatterの引数textpositionを使用することで、テキストの表示位置を変更することができる。プロットデータ自体は変わりないが、テキストの位置を点の左上に置くのか・右下に置くのかなどを指定できる。

今回の例だとmode = 'lines+markers+text'を例として指定。選択可能なtextpositionは以下の合計9種類。デフォルトは’middle center’

  • 'top left': 左上
  • 'top center': 真上
  • 'top right': 右上
  • 'middle left': 左
  • 'middle center': 中心
  • 'middle right': 右
  • 'bottom left': 左下
  • 'bottom center': 真下
  • 'bottom right': 右下
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# textpositionでテキストの位置を変更

x = (0, 1, 2)

# ラインとマーカーとテキストを同時に表示
mode = 'lines+markers+text'

# テキストを置く位置
textpositions = (
    'top left', 'top center', 'top right', 'middle left', 'middle center',
    'middle right', 'bottom left', 'bottom center', 'bottom right'
)

plot = []
for num, textposition in enumerate(textpositions):
    y = np.array((1, 3, 2)) + num
    d = go.Scatter(
        x=x, y=y,
        name=textposition,  # プロットの名前はtextpositionに
        mode=mode, text=textposition,
        textposition=textposition  # テキストを置く位置
    )
    plot.append(d)

fig = go.Figure(data=plot)  # plotは引数data
# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_textposition"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

バブルチャートの作成


散布図は点のグラフなのでバブルチャートの作成も可能。バブルチャートでは点のサイズを変更する必要があるが、これはgo.Scattreの引数markerの中のsizeで調節できる。

ここではさらに引数colorでマーカーの色も変更した。colorの指定方法はいろいろあるがここでは配列の値に応じて自動で色が変わるように設定した。配列の最後の要素8がそのほかの要素よりも大きいので、黄色になっている。

デフォルトのマーカーの色はNoneだが、後述する引数colorscaldeで一括で色を変更可能。選択できるカラー一覧は公式の「Built-in Continuous Color Scales in Python」から確認することができる。

import plotly.graph_objects as go
import plotly.io as pio

# バブルチャートを作成

fig = go.Figure(
    data=go.Scatter(
        x=[1, 2, 3, 4],
        y=[10, 11, 12, 13],
        mode='markers',
        marker=dict(
            size=[40, 60, 80, 100],  # マーカーのサイズ

        )
    )
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_bubble"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

マーカーの色はCSSやGBカラーで変更できる


マーカーの色は後述する引数colorscaleで一括変更できるが、1プロットずつ変更することも可能。プロットの数だけgo.Scatterの引数markerの引数colorを用意すればいい。

指定できる色の形式は以下の4種類。今回はどれもvioletの色になるように指定したが、最後のrgbaでは不透明度を0.2にして薄くしてみた。

  • CSSカラー: ‘violet'
  • HTMLカラー: ‘#ee82ee’
  • RGB: 'rgb(238, 130, 238)'
  • RGBa: 'rgba(238, 130, 238, 0.2)'

なお、プロット点よりcolorで指定した配列の数の方が少ない場合、足りないプロットは全て黒で塗りつぶされるので注意。

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio

# 色んな色の指定方法

fig = go.Figure(
    data=go.Scatter(
        x=[1, 2, 3, 4],
        y=[10, 11, 12, 13],
        mode='markers',
        # マジックアンダースコアを使って書いてもいい
        marker_size=(0, 10, 50, 100),
        # 全てvioletカラー
        marker_color=(
            'violet',  # CSSカラー
            '#ee82ee',  # HTMLカラー
            'rgb(238, 130, 238)',  # rgb(Red, Green, Blue)
            'rgba(238, 130, 238, 0.2)'  # rgba(Red, Green, Blue, alpha)
        ),
    )
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_bubble_color"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

また引数が入れ子(ネスト)の場合はアンダースコア_を使うことで辞書型を使わずに記述することも可能。

ここではmarker_sizeでマーカーのサイズを、marker_colorでマーカーの色を設定した。markerの引数が少ない時はアンダースコアで短く記述するとスッキリするだろう。

colorscaleでプロットカラーをカラーバーで表示


引数colorscaleを指定することで、データ点の値を基準にカラーバーを追加することも可能。colorscaleのデフォルトはNoneだが、これでも紫から黄色にかけてのグラデーションを自動でつけてくれる。

ここではcolorscale='Jet'として青系から赤系のグラデーションでグラフを作成してみた。値の大小を比較する際にはこのJetが一番わかりやすいと思う。

なお、カラースケールの最後に_rをつけることで、色の順番が逆になる。Jetなら青→赤から赤→青に反転する。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# マーカーの色でカラーバーを作成

np.random.seed(0)  # 乱数の固定
y = np.random.randn(500)
fig = go.Figure(
    data=go.Scatter(
        # xを省略するとデータのインデックスがxの値になる
        y=y,  # 500のランダムデータ作成
        mode='markers',
        marker=dict(
            size=16,
            color=y,  # マーカーの色をyにする
            colorscale='Jet',  # カラースケール変更
        )
    )
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_colorscale"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

いろいろなcolorscaleの例





その他のカラースケールでもグラフを作成してみたcolorscales = ('Greys', 'Plotly3', 'Pinkyl', 'Picnic')で4種類のカラースケールを用意し、同じデータで色だけ変えてグラフ化した。

また、それぞれのグラフがどのカラースケールを使ったのかわかるように、titleでグラフタイトルを追加しておいた。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# その他のカラースケールの例

np.random.seed(0)
y = np.random.randn(500)

# カラースケールの一例
colorscales = ('Greys', 'Plotly3', 'Pinkyl', 'Picnic')
for colorscale in colorscales:
    fig = go.Figure(
        data=go.Scatter(
            y=y,
            mode='markers',
            marker=dict(
                size=16, color=y,
                colorscale=colorscale,
            )
        ),
        # グラフタイトルはtitle_textで指定しなくてもいい
        layout=go.Layout(title=colorscale)
    )
    # グラフ全体とホバーのフォントサイズ変更
    fig.update_layout(font_size=20, hoverlabel_font_size=20)
    fig.show()

    # グラフ保存用の関数
    prefix = 'go-scatter'
    save_name = f"{prefix}_colorscale_{colorscale}"
    pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
    pio.write_html(fig, f"{save_name}.html",)
    pio.write_image(fig, f"{save_name}.png")

symbolでマーカーのシンボルを変更


go.Scatterの引数markerの中のsymbolでマーカーのシンボルを変更可能。plotly公式の「Styling Markers in Python」やドキュメントで全てのシンボルについては記述されている。

シンボルは例外はあるが、塗りつぶし・白抜き・中心に点・白抜きと中心に点の4種類が存在している。ここではこれらを’circle’(円)に対して適用、その他メジャーなシンボルでグラフを作成した。

なお、わかりやすいようにマーカーのサイズはmarker_sizeで大きくした。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# マーカーのシンボルを変更

# シンボルの一例
symbols = (
    'circle', 'circle-open', 'circle-dot', 'circle-open-dot',
    'square', 'diamond', 'cross', 'triangle-up'
)

plot = []
for num, symbol in enumerate(symbols):
    y = np.array((1, 3, 2)) + num
    d = go.Scatter(
        x=x, y=y, name=symbol, mode='lines+markers',
        marker_symbol=symbol,  # マーカーのシンボル
        marker_size=20,  # マーカーサイズ変更
    )
    plot.append(d)

fig = go.Figure(data=plot)
# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_symbol"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

dashで線の種類を変更


また、引数dashで線の種類を変更することができる。線についても公式の「Line Charts in Python」やドキュメントで詳細が書かれている。

dashで選択できる線の種類は以下の6種類+1パターン。

  • 'solid': 実線
  • 'dot': 点線
  • 'dash': 破線
  • 'longdash': 長い破線
  • 'dashdot': 一点鎖線
  • 'longdashdot': 長い破線の一点鎖線
  • '5px,10px,2px,2px': 5, 10, 2, 2 pixごとの破線
import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 線の種類を変更

# 線種の一例
dashs = (
    'solid', 'dot', 'dash', 'longdash',
    'dashdot', 'longdashdot', '5px,10px,2px,2px'
)

plot = []
for num, dash in enumerate(dashs):
    y = np.array((1, 3, 2)) + num
    d = go.Scatter(
        x=x, y=y, name=dash,
        line_dash=dash,  # 線の種類
    )
    plot.append(d)

fig = go.Figure(data=plot)
# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_dash"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

add_traceでプロットを追加、update_traceで設定を更新


一度go.FIgurefigを作成しても後からプロットを追加したりプロットの設定を更新することができる。

プロットの追加はfig.add_traceで、すでにfigに入っているプロットの設定の一括更新はupdate_traceで可能だ。

ここでは先にsinを作成し後からcosadd_traceで追加、update_tracesin, cosともにマーカーの設定を更新した。なお、設定の個別更新はfigの中身を直接変更することで可能。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# 0-100までを100分割
t = np.linspace(0, 10, 100)

# 先にプロットデータを入れておく
plot = [go.Scatter(
    x=t, y=np.sin(t),
    name='sin',
    mode='markers',
    marker_color='rgba(152, 0, 0, .8)'  # 不透明度0.8
)]
fig = go.Figure(data=plot)

# add_traceでプロットを追加
fig.add_trace(go.Scatter(
    x=t, y=np.cos(t),
    name='cos',
    marker_color='rgba(255, 182, 193, .9)'  # 不透明度0.9
))

# update_tracesで既存のプロット情報を更新
fig.update_traces(
    mode='markers',  # 点だけに
    marker_line_width=2,  # マーカーの枠線の変更
    marker_size=10  # マーカーサイズ
)

# 0番目のsinだけmodeを変更
fig['data'][0]['mode'] = 'lines+markers'

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_update_traces"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

ホバーのスタイルを設定


plotlyの大きな目玉機能の一つにホバーがあるが、このホバーにデータの内容を表示することが可能。

go.Scatterの引数textに表示したい内容を指定すると好きなデータを表示することができる。今回の例ではpandasで読み込んだデータフレームのState列をホバーに追加表示するように設定した。

これで通常の各データのx, yの下にStateの情報が追加された。

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio# ホバー機能を使う

file = '<https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv>'
data = pd.read_csv(file)  # データの読み込み
print(data)
#     Rank                 State Postal  Population
# 0      1               Alabama     AL   4849377.0
# 1      2                Alaska     AK    736732.0
# 2      3               Arizona     AZ   6731484.0
# 3      4              Arkansas     AR   2966369.0
# 4      5            California     CA  38802500.0
# 5      6              Colorado     CO   5355866.0
# 6      7           Connecticut     CT   3596677.0
# 7      8              Delaware     DE    935614.0
# 8      9  District of Columbia     DC    658893.0
# 9     10               Florida     FL  19893297.0
# 10    11               Georgia     GA  10097343.0
# 11    12                Hawaii     HI   1419561.0
# 12    13                 Idaho     ID   1634464.0
# 13    14              Illinois     IL  12880580.0
# 14    15               Indiana     IN   6596855.0
# 15    16                  Iowa     IA   3107126.0
# 16    17                Kansas     KS   2904021.0
# 17    18              Kentucky     KY   4413457.0
# 18    19             Louisiana     LA   4649676.0
# 19    20                 Maine     ME   1330089.0
# 20    21              Maryland     MD   5976407.0
# 21    22         Massachusetts     MA   6745408.0
# 22    23              Michigan     MI   9909877.0
# 23    24             Minnesota     MN   5457173.0
# 24    25           Mississippi     MS   2994079.0
# 25    26              Missouri     MO   6063589.0
# 26    27               Montana     MT   1023579.0
# 27    28              Nebraska     NE   1881503.0
# 28    29                Nevada     NV   2839098.0
# 29    30         New Hampshire     NH   1326813.0
# 30    31            New Jersey     NJ   8938175.0
# 31    32            New Mexico     NM   2085572.0
# 32    33              New York     NY  19746227.0
# 33    34        North Carolina     NC   9943964.0
# 34    35          North Dakota     ND    739482.0
# 35    36                  Ohio     OH  11594163.0
# 36    37              Oklahoma     OK   3878051.0
# 37    38                Oregon     OR   3970239.0
# 38    39          Pennsylvania     PA  12787209.0
# 39    40           Puerto Rico     PR   3548397.0
# 40    41          Rhode Island     RI   1055173.0
# 41    42        South Carolina     SC   4832482.0
# 42    43          South Dakota     SD    853175.0
# 43    44             Tennessee     TN   6549352.0
# 44    45                 Texas     TX  26956958.0
# 45    46                  Utah     UT   2942902.0
# 46    47               Vermont     VT    626562.0
# 47    48              Virginia     VA   8326289.0
# 48    49            Washington     WA   7061530.0
# 49    50         West Virginia     WV   1850326.0
# 50    51             Wisconsin     WI   5757564.0
# 51    52               Wyoming     WY    584153.0

fig = go.Figure(
    data=go.Scatter(
        x=data['Postal'],
        y=data['Population'],
        mode='markers',
        marker_color=data['Population'],  # 色はPopulationに対応
        text=data['State'],  # modeがtextでないときはホバーに反映
        marker_colorscale='Jet'
    ),
    layout=dict(title='Population of USA States')
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_hover"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

customdataでホバーに置く情報を自由に変更


go.Scatterの引数textで好きな情報をホバーに置くことができたが、複数データを置きたい場合はcustomdataを使うと便利。

customdatalilstpandasのシリーズデータを指定して、customdata[0]のようにインデックスでデータを取り出せるようにする引数だ。

以下の例だと読み込んだcsvファイルをそのままcustomdataに使用し、customdata[0]Rankcustomdata[3]Populationを取り出せるようにした。

file = '<https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv>'
data = pd.read_csv(file)  # データの読み込み
print(data)
#     Rank                 State Postal  Population
# 0      1               Alabama     AL   4849377.0
# 1      2                Alaska     AK    736732.0
...

なお、ホバーの表示を変更はgo.Scaterの引数hovertemplateで可能。%{データ}の形式で配列を指定することで各データ点にホバーを追加してくれる。

例えば横軸の値を表示したい場合は%{x}で表示することができる。なお、hovertemplateではhtmlの文法を使えるので、改行したいときは<br>、太文字は<strong>といったタグが使用可能。

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio

# customdataで好きなデータをホバーに置く

file = '<https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv>'
data = pd.read_csv(file)

fig = go.Figure(
    data=go.Scatter(
        x=data['Postal'], y=data['Population'], mode='markers',
        marker_color=data['Population'],
        customdata=data,  # データフレーム全体を使用してみる
        # 0番目がRank, 1番目がState
        hovertemplate='Rank: %{customdata[0]}, State: %{customdata[1]}, Population: %{customdata[3]}',
        marker_colorscale='Jet'
    ),
    layout=dict(title='Population of USA States')
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_customdata"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

customdataを名前で指定


customdataは好きな情報を配列で管理できるから楽だが、[0]というようにインデックスでの指定だと順番を意識しないといけないから使いづらい。

しかし、customdataでデータフレームを使用していたらカラム名(列名)を指定することでもデータ抽出が可能。

Rankの場合だと%{customdata.Rank}と指定することで%{customdata[0]}と同じ出力になる。

カラム名が整数の場合でも同じようにcustomdata.1のように指定できるが、0.1のように小数点だとcustomdata.0.1となり区切り位置が不明でデータが出力されないので注意。なお、エラーは吐かれず、ホバーにcustomdataの文字がそのまま出力される。

 

仮に小数を使いたい場合はデータフレームのカラム名を文字列にしたりcustomdataを文字列で指定しても表示できなかったので、この場合はインデックスで指定するのが良いだろう。

import numpy as np
import pandas as pd
import plotly.graph_objects as go
import plotly.io as pio

# customdataを名称で指定

file = '<https://raw.githubusercontent.com/plotly/datasets/master/2014_usa_states.csv>'
data = pd.read_csv(file)

customdata = []
for row in data.iloc:
    # 各行のデータをdictに変換して格納
    customdata.append(dict(row))

# 0行目のデータ
print(customdata[0])
# {'Rank': 1, 'State': 'Alabama', 'Postal': 'AL', 'Population': 4849377.0}

fig = go.Figure(
    data=go.Scatter(
        x=data['Postal'], y=data['Population'], mode='markers',
        marker_color=data['Population'],
        customdata=customdata,
        # 各データごとにdictでまとめていると、customdataを名称で指定可能
        hovertemplate='Rank: %{customdata.Rank}, State: %{customdata.State}'
    ),
    layout=dict(title='customdata(set dict)')
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_customdata_name"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

Scatterglで大量のデータを軽く扱う


最後にgo.Scatterglを使用した、大量データのプロット方法について解説する。ざっくりいうとWebGLなるものを使って軽くするということ。

散布図の場合はgo.Scattreglを使用することで軽くグラフを作成することが可能になる。glなしの通常のgo.Scatterだと動かせない程重いグラフになるが、glありだとスルスル動かせる。

今回は1万データで乱数を作成しプロットした。なお、line_widthでマーカーの枠線の太さを1として枠線が見えるようにした。

import numpy as np
import plotly.graph_objects as go
import plotly.io as pio

# Scatterglで大量のデータも軽く作成

# 1万データ作成
N = 10000
np.random.seed(1)
x = np.random.randn(N)
np.random.seed(2)
y = np.random.randn(N)

fig = go.Figure(
    # go.Scatterglで大データも軽く操作可能
    data=go.Scattergl(
        x=x, y=y, mode='markers',
        marker=dict(
            color=np.random.randn(N),
            colorscale='Viridis',
            line_width=1,  # マーカーの線の太さ
        )
    )
)

# グラフ全体とホバーのフォントサイズ変更
fig.update_layout(font_size=20, hoverlabel_font_size=20)
fig.show()

# グラフ保存用の関数
prefix = 'go-scatter'
save_name = f"{prefix}_scattergl"
pio.orca.config.executable = '/Applications/orca.app/Contents/MacOS/orca'
pio.write_html(fig, f"{save_name}.html",)
pio.write_image(fig, f"{save_name}.png")

1万データくらいなら割とスルスル動かせるが、100万データにするとちょっとカクツキが見られた。もちろんPCのスペックにも左右されるだろうが、それなりに高性能なPCでこれだからデータ数はほどほどにしたい。

go.Scatterglは以下の記事で詳しく解説しているので併せてご覧いただきたい。

【Plotlyで散布図】go.Scatterglで大量のデータでグラフを作成する

今回はPythonのPlotlyで大量のデータを軽く扱うことができるgo.Scattergl ...

続きを見る

まずは基本から学ぶ

ということで、今回はplotlygoを使って散布図を作成する方法を解説した。散布図は基本的なグラフなので紹介した内容以外でもいろいろカスタムできるが、まずは基本から学んでほしい。

といったものの、本記事の内容を応用すれば他の種類のグラフも同じように作成することできる。なのでまずは本記事の内容やplotlyのグラフ作成の手順を知り、身につけてほしい。

関連記事

【Plotly&ボタン】updatemenusとbuttonsでボタン機能を追加

Plotlyはプロットしたデータを動かすことができるのが大き ...

続きを見る

【Plotly&ボタン】updatemenusのargs2で2回目のボタン押下機能を追加

今回はPlotlyのボタン機能に2回目のボタン押下の処理を追加& ...

続きを見る

【Plotly&sliders】スライダーを追加しデータを切り変える

本記事ではPlotlyでデータの流れを簡単に理解できる機能の ...

続きを見る

【Pythonを独学】社会人が1人で学習できるのか。結論、学べるが...

今回は社会人がプログラミング言語「Python」を独学で学習 ...

続きを見る

Pythonを効率的に学びたいなら

本記事を読んでもっとPythonを学びたいと思った人もいるだろう。ただ、どうせ学ぶなら効率的に学びたい。

就職するにも転職するにも教養として身に付けたいにしろ、遠回りして学習するのはもったいない。

独学でもなんとかなるが

正直、Pythonの学習は独学でもある程度なんとかなると思う。というより他の言語も独学でなんとかなるのが現実。ただ、なんとかなるとしても以下の問題は見逃せない。

  • プログラミングをやらなくても正直問題ない
  • 何をしたらいいのかわからない
  • どう学習したらいいのかわからない
  • これで合っているのかわからない
  • 時間が足りない

私は大学・大学院の研究でPythonを使用、この時に教えてくれる人がいなかったので独学でPythonを学んで大学院の修士論文が通った。

ただ、あくまでもそれは、

  • 大学の研究の過程で必要
  • 何をしないといけないか明白
  • 大学の研究室が超ホワイト
  • 大学生だから時間があった

という「学生」という身分だから独学で学べただけ。すでに社会人の人は時間がないからかなりキツい。

さらに現在大学生の人も大学の授業や研究室が忙くてなかなか独学が難しいという人もいる。

特に社会人は難しい

以下の記事でも解説したが、特に社会人は日々の仕事に追われプライベートが疎かになりがちだ。そこでさらにプログラミングを学ぼうとするとかなりハードルが高い。

今の生活を振り返って自力で独学で学ぶ覚悟と根気と時間があるか確認してほしい。

【Pythonを独学】社会人が1人で学習できるのか。結論、学べるが...

今回は社会人がプログラミング言語「Python」を独学で学習 ...

続きを見る

スクールだと目的と目標がはっきりする

また、プログラミングを学習したいけど何をしたらいいのかわからない、どうしたらいいのかわからないという漠然とした不安がある人も多いだろう。

そんな人はプログラミングスクールに通うことをおすすめする。スクールだと、

  • 何をすればいいのかわかる
  • したいことがなくてもアドバイスをもらえる
  • 学習方法を教えてもらえる

といったメリットがある。何をするかが分かれば最初の一歩は踏み出しやすい。最初が踏み出せないから今立ち止まっているのだから。

さらに独学とは違いそれなりに費用がかかるので、サボるとかなりもったいない。

スクールで客観的視点を持つ

また、現役でエンジニアとして働く私からいうと、独学で学んだコードは我流で実務では使いづらいことも多い。

このサイトで紹介するコードはあくまでも最初の学習をメインとしているから簡素にしているが、実務ではしっかりと汎用性や保守性を担保しないといけない。

そんな中で独学で突っ走ると転職するにも就職するにもその後がかなりしんどい。

プログラミング学習のショートカットはスクール

結論、独学でPythonを学ぶことは可能。しかし効率的かつ汎用的なスキルを身に付けたいならスクールに通うのが1番だ。特に未経験者はなおさら。

私はプログラミング経験があることで転職で若手なのに年収が数十万円も増えたしプログラミングの知識があることで周りから一目置かれることも。

Pythonに限らずだがプログラミングに興味があれば是非ともトライしていただきたい。

  • この記事を書いた人
  • 最新記事

メガネ

ベンチャー企業のWebエンジニア駆け出し。独学のPythonで天文学系の大学院を修了→転職→今に至る。最近は主にPHPを触ってます。 メインのブログは「M天パ」https://megatenpa.com/です。

-go(plotly.graph_objects)
-, , ,