カテゴリー

Pythonでの比較

【plotly&ボタンとスライダー】goとpxでのupdatemenusとsliders

2021年10月31日

こんな人にオススメ

plotlyってgopxがあるけど、それぞれでボタン・スライダーを作成するのはどうしたらいいの?

書き方とかって異なる?

ということで、今回はplotlygoplotly.graph_objects)とpxplotly.express)でボタンつき、スライダーつきのグラフを作成する。

go, pxそれぞれでグラフを描く方法は異なるけど、ボタンについてはかなり似ている。スライダーはかなり異なる。

python環境は以下。

  • Python 3.9.7
  • pandas 1.3.3
  • numpy 1.21.2
  • plotly 5.3.1
  • plotly-orca 3.4.2

運営者のメガネとです。YouTubeTwitterInstagramも運営中。

自己紹介はこちらから、お問い合わせはこちらからお願いいたします。

運営者メガネ

作成したコード全文

下準備

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

まずは下準備のimport関連。今回は自作テンプレートは使用しない。シンプルにデフォルトのグラフを作成する。

【随時更新 備忘録】plotlyのグラフ即席作成コード

こんな人にオススメ plotlyって{ ...

続きを見る

使用するデータ

# 横軸は-2から+2までを0.1刻み
x = np.arange(-2, 2 + 0.1, 0.1)
print(x)
# [-2.00000000e+00 -1.90000000e+00 -1.80000000e+00 -1.70000000e+00
#  -1.60000000e+00 -1.50000000e+00 -1.40000000e+00 -1.30000000e+00
#  -1.20000000e+00 -1.10000000e+00 -1.00000000e+00 -9.00000000e-01
#  -8.00000000e-01 -7.00000000e-01 -6.00000000e-01 -5.00000000e-01
#  -4.00000000e-01 -3.00000000e-01 -2.00000000e-01 -1.00000000e-01
#   1.77635684e-15  1.00000000e-01  2.00000000e-01  3.00000000e-01
#   4.00000000e-01  5.00000000e-01  6.00000000e-01  7.00000000e-01
#   8.00000000e-01  9.00000000e-01  1.00000000e+00  1.10000000e+00
#   1.20000000e+00  1.30000000e+00  1.40000000e+00  1.50000000e+00
#   1.60000000e+00  1.70000000e+00  1.80000000e+00  1.90000000e+00
#   2.00000000e+00]

今回使用するデータは-2から2までを0.1刻みにした配列を横軸に、この横軸を1から5次関数として計算した配列を縦軸とする。

各○次関数はどのデータかがわかりやすいようにdictに格納しておく。これで配列にラベルをつけることができる。

# 縦軸は1次関数から5次関数まで
data = {}
for order in range(1, 6):
    data[f"order{order}"] = x ** order
print(data)
# {'order1': array([-2.00000000e+00, -1.90000000e+00, -1.80000000e+00, -1.70000000e+00,
#        -1.60000000e+00, -1.50000000e+00, -1.40000000e+00, -1.30000000e+00,
#        -1.20000000e+00, -1.10000000e+00, -1.00000000e+00, -9.00000000e-01,
#        -8.00000000e-01, -7.00000000e-01, -6.00000000e-01, -5.00000000e-01,
#        -4.00000000e-01, -3.00000000e-01, -2.00000000e-01, -1.00000000e-01,
#         1.77635684e-15,  1.00000000e-01,  2.00000000e-01,  3.00000000e-01,
#         4.00000000e-01,  5.00000000e-01,  6.00000000e-01,  7.00000000e-01,
#         8.00000000e-01,  9.00000000e-01,  1.00000000e+00,  1.10000000e+00,
#         1.20000000e+00,  1.30000000e+00,  1.40000000e+00,  1.50000000e+00,
#         1.60000000e+00,  1.70000000e+00,  1.80000000e+00,  1.90000000e+00,
#         2.00000000e+00]), 'order2': array([4.00000000e+00, 3.61000000e+00, 3.24000000e+00, 2.89000000e+00,
#        2.56000000e+00, 2.25000000e+00, 1.96000000e+00, 1.69000000e+00,
#        1.44000000e+00, 1.21000000e+00, 1.00000000e+00, 8.10000000e-01,
#        6.40000000e-01, 4.90000000e-01, 3.60000000e-01, 2.50000000e-01,
#        1.60000000e-01, 9.00000000e-02, 4.00000000e-02, 1.00000000e-02,
#        3.15544362e-30, 1.00000000e-02, 4.00000000e-02, 9.00000000e-02,
#        1.60000000e-01, 2.50000000e-01, 3.60000000e-01, 4.90000000e-01,
#        6.40000000e-01, 8.10000000e-01, 1.00000000e+00, 1.21000000e+00,
#        1.44000000e+00, 1.69000000e+00, 1.96000000e+00, 2.25000000e+00,
#        2.56000000e+00, 2.89000000e+00, 3.24000000e+00, 3.61000000e+00,
#        4.00000000e+00]), 'order3': array([-8.00000000e+00, -6.85900000e+00, -5.83200000e+00, -4.91300000e+00,
#        -4.09600000e+00, -3.37500000e+00, -2.74400000e+00, -2.19700000e+00,
#        -1.72800000e+00, -1.33100000e+00, -1.00000000e+00, -7.29000000e-01,
#        -5.12000000e-01, -3.43000000e-01, -2.16000000e-01, -1.25000000e-01,
#        -6.40000000e-02, -2.70000000e-02, -8.00000000e-03, -1.00000000e-03,
#         5.60519386e-45,  1.00000000e-03,  8.00000000e-03,  2.70000000e-02,
#         6.40000000e-02,  1.25000000e-01,  2.16000000e-01,  3.43000000e-01,
#         5.12000000e-01,  7.29000000e-01,  1.00000000e+00,  1.33100000e+00,
#         1.72800000e+00,  2.19700000e+00,  2.74400000e+00,  3.37500000e+00,
#         4.09600000e+00,  4.91300000e+00,  5.83200000e+00,  6.85900000e+00,
#         8.00000000e+00]), 'order4': array([1.60000000e+01, 1.30321000e+01, 1.04976000e+01, 8.35210000e+00,
#        6.55360000e+00, 5.06250000e+00, 3.84160000e+00, 2.85610000e+00,
#        2.07360000e+00, 1.46410000e+00, 1.00000000e+00, 6.56100000e-01,
#        4.09600000e-01, 2.40100000e-01, 1.29600000e-01, 6.25000000e-02,
#        2.56000000e-02, 8.10000000e-03, 1.60000000e-03, 1.00000000e-04,
#        9.95682444e-60, 1.00000000e-04, 1.60000000e-03, 8.10000000e-03,
#        2.56000000e-02, 6.25000000e-02, 1.29600000e-01, 2.40100000e-01,
#        4.09600000e-01, 6.56100000e-01, 1.00000000e+00, 1.46410000e+00,
#        2.07360000e+00, 2.85610000e+00, 3.84160000e+00, 5.06250000e+00,
#        6.55360000e+00, 8.35210000e+00, 1.04976000e+01, 1.30321000e+01,
#        1.60000000e+01]), 'order5': array([-3.20000000e+01, -2.47609900e+01, -1.88956800e+01, -1.41985700e+01,
#        -1.04857600e+01, -7.59375000e+00, -5.37824000e+00, -3.71293000e+00,
#        -2.48832000e+00, -1.61051000e+00, -1.00000000e+00, -5.90490000e-01,
#        -3.27680000e-01, -1.68070000e-01, -7.77600000e-02, -3.12500000e-02,
#        -1.02400000e-02, -2.43000000e-03, -3.20000000e-04, -1.00000000e-05,
#         1.76868732e-74,  1.00000000e-05,  3.20000000e-04,  2.43000000e-03,
#         1.02400000e-02,  3.12500000e-02,  7.77600000e-02,  1.68070000e-01,
#         3.27680000e-01,  5.90490000e-01,  1.00000000e+00,  1.61051000e+00,
#         2.48832000e+00,  3.71293000e+00,  5.37824000e+00,  7.59375000e+00,
#         1.04857600e+01,  1.41985700e+01,  1.88956800e+01,  2.47609900e+01,
#         3.20000000e+01])}

このdictデータでgoのプロットはできるが、pxについてはこのままだと使いにくいのでpandasのデータフレームに変換しておく。

px用にデータフレームに変換

px_data = {'x': x.tolist() * len(data)}  # データをまとめる用のdict
px_y = []  # px用のyの値
order = []  # px用のオーダーの値
# 各データごとにdictに格納
for num, val in enumerate(data.values(), 1):
    px_y.append(val.tolist())  # listに変換して後から展開
    order.append([f"{num}"] * len(val))  # 各データの数だけオーダーの値も複製

データフレームの列は横軸のx、縦軸のy、そして各次数のorderを名称とする。orderは1次関数のデータが続いている間はずっと1を示し続ける。

orderを設定しておくことで、どこまでが1次関数なのかというような判断が可能となる。ただし、orderは文字列ではなく数値にしておくと、凡例作成時に自動でカラーバーができてしまうので注意。

また、上のコードだとpx_yorderはそれぞれ2次元配列になっている。

# 現状だと2次元配列になっているから展開して1次元配列に
print(order)
# [['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1'], ['2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2'], ['3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3'], ['4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4'], ['5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5']]

なので1次元配列に変換する。そうしないとデータフレームにするのが面倒になる。

px_y = sum(px_y, [])  # yの値を展開
order = sum(order, [])  # オーダーの値を展開
print(order)
# ['1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '5']

あとはできたデータをdictに入れてからデータフレームに変換。これでpx用のデータフレームが完成。

# データをdictに入れる
px_data['y'] = px_y
px_data['order'] = order
# データフレームに変換
df = pd.DataFrame(px_data)
print(df)
#        x         y order
# 0   -2.0  -2.00000     1
# 1   -1.9  -1.90000     1
# 2   -1.8  -1.80000     1
# 3   -1.7  -1.70000     1
# 4   -1.6  -1.60000     1
# ..   ...       ...   ...
# 200  1.6  10.48576     5
# 201  1.7  14.19857     5
# 202  1.8  18.89568     5
# 203  1.9  24.76099     5
# 204  2.0  32.00000     5

# [205 rows x 3 columns]

諸関数の定義

ここではグラフ作成に使用する関数を定義する。以下の2つを定義する。

  1. ボタン・スライダーの内容作成の関数
  2. グラフ保存用の関数

ボタン・スライダーの内容作成の関数

# ボタン・スライダー作成
def set_menus():
    # ボタン・スライダーの内容を作成
    length = len(data)
    # ボタン・スライダーは全プロット表示と各プロット表示で2つに分けて作成

    # 全プロット表示用のボタン・スライダー作成
    visible = [True] * length
    menu = dict(
        label='All', method='update',
        args=[dict(visible=visible), dict(title='All')]
    )
    menus = [menu]  # ボタン・スライダー全体の設定のlistに格納

    # 各プロットのみを表示するためのボタン・スライダー作成
    for num, order in enumerate(data):
        # 一旦全てのプロットを非表示に
        visible = [False] * length
        # 該当するボタン・スライダーのプロット部分だけ表示にして、ラベルを作成
        visible[num] = True

        menu = dict(
            label=order, method='update',
            args=[dict(visible=visible), dict(title=order)]
        )
        menus.append(menu)

    return menus

設定内容としてはボタンもスライダーも共通。以下の2条件を満たせばいい。

  1. 全プロット表示
  2. 各プロット表示、その他のプロットは非表示

ボタンやスライダーについて詳しくは以下を参照してほしいが、今回だとvisibleで指定したboolTrueだと表示、Falseだと非表示。

【plotly&ボタン】plotlyのupdatemenusにbuttonsを追加

こんな人にオススメ plotlyって| ...

続きを見る

【plotly&スライダー】plotlyのslidersにスライダーを追加

こんな人にオススメ plotlyでは| ...

続きを見る

また、argsの初めのdictがプロットに関する内容、2つ目のdictがレイアウトに関する内容を示している。ここを逆にしてもエラーとはならず何も起きないだけ。

グラフ保存用の関数

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

グラフの保存形式はhtmlとpngにした。plotlyのグラフ保存については以下で解説している。

plotlyでグラフを静止画として保存する際に出るポップアップ
【plotly&orca】plotlyで静止画保存(orca)

こんな人にオススメplotlyで画ࠔ ...

続きを見る

また、configはグラフ右上のツールバーだが、今回はごちゃごちゃするのでNoneと指定して無効にする。

ボタンとスライダー設定

set_menus関数でボタン・スライダーの内容の設定はできるので、ここではこれらの設定をグラフに反映させる設定を行う。

ボタン(updatemenus)とスライダー(sliders)では引数が異なるのでここでは分けて考えることにする。

ボタンの設定

updatemenus = [
    dict(
        active=0, buttons=set_menus(), type='buttons',
        direction="right", x=0.5, y=1.01, xanchor='center', yanchor='bottom',
    )]

まずはボタンから。各引数は以下。

  • active: グラフの初期表示プロットのインデックス(0は0番目のプロットを表示)
  • buttons: ボタン設定
  • type: buttonsでボタンを表示、dropdownでドロップダウン形式にできる
  • directon: ボタンを並べる方向
  • x, y: どの位置にボタンを並び始めるか
  • xanchor, yanchor: x, yの位置の基準

注意点はlistの中でdictを作成しないといけない点。listの中で作成するということは、裏を返せば複数ボタン作成可能ということ。

今回でいえばどのプロットを表示するかって話だったけど、別の位置に背景色を変更するとかのボタンも作成可能。

【plotly&ボタン】グラフに複数種のボタンを追加

こんな人にオススメ plotlyって| ...

続きを見る

スライダーの設定

sliders = [
    dict(
        active=0,
        currentvalue=dict(prefix='now: '),
        steps=set_menus()
    )
]

スライダーも同じように設定する。ボタンの時と異なる引数は以下。

  • currentvalue: スライダーの現在の値に関する設定
  • prefix: 現在の値に接頭辞をつける
  • steps: スライダー設定

こちらも同じようにlistの中にdictを入れないといけない。

goでボタンとスライダーを作成

# 各プロットの作成
plot = []
for order, y in data.items():
    d = go.Scatter(x=x, y=y, name=f"go-{order}", showlegend=True)
    plot.append(d)

ということで準備が終わったのでgoでのボタンとスライダーのグラフを作成。の前にプロットデータを作成、レイアウトの関数を定義しておく。

プロットデータとレイアウトの関数はgoでしか使用しないのでここで定義しておく。プロットデータのshowlegendTrueとしておくとプロットが1つでも凡例が出るようになる。

レイアウトに関しては初期グラフタイトルと横・縦軸の表示範囲、そしてボタンとスライダーの設定ができるように追加設定用のkwargsを入れた。

# レイアウトの作成
def set_layout(**kwargs):
    layout = go.Layout(
        title=dict(text='ALL',),  # 初期グラフタイトル
        xaxis_range=(-2.1, 2.1), yaxis_range=(-35, 35),
        **kwargs,  # 追加設定
    )
    return layout

軸の表示範囲を固定しておかないと各プロットごとに自動で範囲が調節されたり、プロットがはみ出たりしてキレイではない。

go x ボタン


まずはgoとボタンの組み合わせ。figdataにプロットデータのplotを、レイアウト部分にボタン情報を含んだset_layout関数を入れたらいい。

ボタンを押すことでプロットが変わることがわかるだろう。

# goでボタン
fig = go.Figure(data=plot, layout=set_layout(updatemenus=updatemenus))
fig.show()
save(fig=fig, config=None, save_name='go_buttons')

go x スライダー


スライダーも同じようにレイアウトにスライダーを入れたら完成。

# goでスライダー
fig = go.Figure(data=plot, layout=set_layout(sliders=sliders))
fig.show()
save(fig=fig, config=None, save_name='go_sliders')

go x ボタン&スライダー


やる意味はないけど、ボタンとスライダーを同時に設定することも可能。しかし、ボタンとスライダーは同期されておらず、片方を動かしてももう片方は止まったまま。

なので、同期するように設定しないと誤解を生みそうだ。というより、そもそもこのグラフでは両方はいらない。

# ボタンとスライダーを両方
layout = set_layout(updatemenus=updatemenus, sliders=sliders)
fig = go.Figure(data=plot, layout=layout)
fig.show()
save(fig=fig, config=None, save_name='go_buttons_sliders')

pxでボタンとスライダーを作成

最後にpxでも同じようにボタンとスライダーを作成する。ボタンについてはgoと似ているけど、スライダーに関してはちょっとトリッキーな方法で作成。

px x ボタン


pxのボタンの場合はすぐにできるというわけではなく、figを作成した後にupdatemenusを設定する。要するに後付け。

px.scatterの引数でボタン関連がないから仕方なくこのようにするしかない。また、デフォルトでは点のプロットとなる。

# pxのボタンの場合はレイアウトに後付けしないといけない
fig = px.scatter(df, x='x', y='y', color='order')
fig.update_layout(updatemenus=updatemenus)
fig.show()
save(fig=fig, config=None, save_name='px_buttons')

px x スライダー


スライダーについては後付けではなく、後削りの戦法。これはかなりトリッキーだが賢いと感じた。

どういうことかというと、スライダーというのがアニメーションから再生ボタンを削除したものという考えから、アニメーションを作成後に再生ボタンを削除する。

例えば以下のようのアニメーションを作成したとする。

# pxのスライダーはアニメーションから再生ボタンを消す
fig = px.scatter(
    df, x='x', y='y', color='order',
    animation_frame="order",  # アニメーションはオーダーごと
    range_x=(-2.1, 2.1), range_y=(-35, 35),
)

この時のfigの中身は以下。

ここから再生ボタン部分を削除する。再生ボタンはupdatemenusでしか使用しないから、実質updatemunusを削除したのと同じ。

fig["layout"].pop("updatemenus")  # 再生ボタンを削除

あとはシンプルにfigを表示してグラフを保存すればいい。まとめると以下。

# pxのスライダーはアニメーションから再生ボタンを消す
fig = px.scatter(
    df, x='x', y='y', color='order',
    animation_frame="order",  # アニメーションはオーダーごと
    range_x=(-2.1, 2.1), range_y=(-35, 35),
)
fig["layout"].pop("updatemenus")  # 再生ボタンを削除

fig.show()
save(fig=fig, config=None, save_name='px_sliders')

px x ボタン&スライダー


最後にpxとボタンとスライダーのグラフを作成したが、スライダーでupdatemenusを消さなければいけないのでとりあえずアニメーションにボタンをつけた。

するとバグった。全プロット表示とorder1がそれぞれ再生ボタンと停止ボタンとなってしまい、使用できない。さらにボタンを押すとプロットが消える。

これだと実用性がないので、使用する際にはうまく両立できるように工夫しないといけない。

# pxでボタンとスライダーを同時するとバグる

fig = px.scatter(
    df, x='x', y='y', color='order',
    animation_frame="order",  # アニメーションはオーダーごと
    range_x=(-2.1, 2.1), range_y=(-35, 35),
)
fig.update_layout(updatemenus=updatemenus)
# fig["layout"].pop("updatemenus")  # 再生ボタンを削除

fig.show()
save(fig=fig, config=None, save_name='px_buttons_sliders')

なお、updatemenusを設定した後に削除すると、普通にスライダーとなる。そりゃそうだ。消したもん

ボタンは共通点多し、スライダーは結構異なる

今回はplotlygopxを使用してボタンを描く方法とスライダーを描く方法について解説した。

それぞれでグラフを描く方法は異なるけど、ボタンの指定方法は同じだったので、ボタンについては好みになりそう。

一方でスライダーに関しては大きく異なるのでスライダーはデータの作成方法や指定のしやすさで決めるのが良さそうだ。

関連記事

【px&animation】plotly.expressでアニメーションのグラフを作成

こんな人にオススメ plotlyでア| ...

続きを見る

【Plotly&animation】Plotlyのgoでアニメーションを作成

こんな人にオススメ plotlyでア| ...

続きを見る

【px&facet】plotly.expressでsubplotsを描く

こんな人にオススメ plotly.express、px ...

続きを見る

【plotly&ボタン】plotlyのupdatemenusに2回押し対応のbuttonsを追加

こんな人にオススメ plotlyでボ| ...

続きを見る

スイッチボット

2022/11/28

【SwitchBotロックレビュー】これからのスタンダードになりうるスマートロック

こんな人にオススメ SwitchBotからスマートロック「SwitchBotロック」が発売された ...

生活に役立つ

2022/11/28

【メガネ厳選】クソ便利に使っているサービスやアイテム達

このページでは執筆者「メガネ」が実際に使って便利だと感じているサ ...

マウス

2022/9/11

【Logicool MX ERGO vs MX Master 3】ERGOをメインにした決定的な理由

こんな疑問・お悩みを持っている人におすすめ 執筆者はLogicoolのハイエンӠ ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【ながら聴きイヤホン比較】SONY LinkBuds、ambie、BoCoはどれがおすすめ?

こんな人におすすめ 耳を塞がない開放型のイヤホンに完全ワイヤレスӟ ...

macOSアプリケーション

2022/10/15

【M1 Mac】MacBook Proに入れている便利でニッチなアプリを21個紹介する

こんな人におすすめ MacBookを購入してLINEとか必要最低限のアプリは入れた。 ...

完全ワイヤレスイヤホン(TWS)

2022/10/23

【SENNHEISER MOMENTUM True Wireless 3レビュー】高レベルでバランス型の高音質イヤホン

こんな人におすすめ SENNHEISER MOMENTUM True Wireless 3って実際のところどうなの? 評判は良い ...

完全ワイヤレスイヤホン(TWS)

2022/11/21

【SONY WF-1000XM4レビュー】神とゴミのハーフ&ハーフ

こんな人におすすめ SONYのフラグシップモデル「SONY WF-1000XM4」ってどれくらい性 ...

完全ワイヤレスイヤホン(TWS)

2022/8/19

【Nothing ear (1)レビュー】ライトな完成度、アップデートに期待

こんな人にオススメ 完全ワイヤレスイヤホン(TWS)でスケルトンボディ ...

Pythonを学びたいけど独学できる時間なんてない人へのすゝめ

執筆者は大学の研究室・大学院にて独学でPythonを習得した。

でも社会人になったら独学で行うには時間も体力もなくて大変だ。

時間がない社会人だからこそプロの教えを乞うのが効率的。

ここでは色んなタイプに合ったプログラミングスクールの紹介をする。

  • この記事を書いた人

メガネ

ベンチャー企業のWebエンジニア駆け出し。独学のPythonで天文学系の大学院を修了→新卒を1.5年で辞める→転職→今に至る。
常時金欠のガジェット好きでM1 MacBook Pro x Galaxy S22 Ultraの狂人。
人見知りで根暗だったけど、人生楽しもうと思って良い方向に狂う→人生が楽しい

ガジェットのレビューとPythonコードを記事にしています。ぜひ楽しんでください🦊
自己紹介と半生→変わって楽しいの繰り返し

-Pythonでの比較
-, , ,