本記事ではPythonのグラフライブラリとして使えるplotlyによる「平行座標プロット」の作成について紹介します。
2021年現在も流行している機械学習コンテストなど、データサイエンスという分野で用いられることがある平行座標プロット。
特徴として変数間やカテゴリ間の相関関係を可視化できる点が挙げられます。
どの関係性に目をつけるべきか知れるツールとして使えます。
今回もplotlyチュートリアルの平行カテゴリ図と平行座標プロットから例題を抜粋しながら解説していきます。
①px.parallel_categoriesを使用した平行カテゴリ図
②色で区分する平行カテゴリ図
③go.Parcatsを使用した平行カテゴリ図
④go.Parcats+色区別を使用した平行カテゴリ図
⑤go.FigureWidgetを使用した散布図+平行カテゴリ図
⑥px.parallel_coordinatesを使用した平行座標プロット
⑦go.Parcoordsを使用した平行座標プロット
今回紹介する例題ではグラフの元データを容易する必要がなく、下記プログラムを完コピすればグラフを作成することができます。
まずは実際に手を動かしてコードを書いて見てください。
AnacondaのインストールとJupyter notebookの準備
Anacondaのインストールがまだの方はこちらの記事を参考に準備してください。
Jupyter notebookの起動と使い方まで紹介しています。
plotlyとplotly_expressのインストール
導入から基本的な使い方まで紹介しています。
それでは平行座標プロットについて解説していきます。
px.parallel_categoriesを使用した平行カテゴリ図
plotly_express、plotly_graph_objectsを使用するので、まずはインポートします。
import plotly.express as px
import plotly.graph_objects as go
元データはplotly_expressで用意されているdata.tipsを使用します。
tipsの中には合計消費量(totall_bill)(チップを除く)、チップ量(tip)、顧客の性別(sex)、消費した曜日(day)、消費期間(time)、食事回数(size)を含む7つのフィールドが含まれています。
fig=px.parallel_categories()の一文で平行カテゴリ図が書けます。
df = px.data.tips()
fig = px.parallel_categories(df)
fig.show()
②色で区分する平行カテゴリ図
①に加えてcolor=”size”とすることでサイズによって色が区別されるようになります。
df = px.data.tips()
fig = px.parallel_categories(df, dimensions=['sex', 'smoker', 'day'],
color="size", color_continuous_scale=px.colors.sequential.Inferno,
labels={'sex':'Payer sex', 'smoker':'Smokers at the table', 'day':'Day of week'})
fig.show()
③go.Parcatsを使用した平行カテゴリ図
go.Parcatsを使用しても書くことができます。
fig = go.Figure(go.Parcats(
dimensions=[
{'label': 'Hair',
'values': ['Black', 'Brown', 'Brown', 'Brown', 'Red']},
{'label': 'Eye',
'values': ['Brown', 'Brown', 'Brown', 'Blue', 'Blue']},
{'label': 'Sex',
'values': ['Female', 'Male', 'Female', 'Male', 'Male']}],
counts=[6, 10, 40, 23, 7]
))
fig.show()
④go.Parcats+色区別を使用した平行カテゴリ図
色の他にもhoveron、hoverinfo、labelfont、tickfont、arrangementなどの引数が使えます。
titanic_df = pd.read_csv("https://raw.githubusercontent.com/plotly/datasets/master/titanic.csv")
# Create dimensions
class_dim = go.parcats.Dimension(
values=titanic_df.Pclass,
categoryorder='category ascending', label="Class"
)
gender_dim = go.parcats.Dimension(values=titanic_df.Sex, label="Gender")
survival_dim = go.parcats.Dimension(
values=titanic_df.Survived, label="Outcome", categoryarray=[0, 1],
ticktext=['perished', 'survived']
)
# Create parcats trace
color = titanic_df.Survived;
colorscale = [[0, 'lightsteelblue'], [1, 'mediumseagreen']];
fig = go.Figure(data = [go.Parcats(dimensions=[class_dim, gender_dim, survival_dim],
line={'color': color, 'colorscale': colorscale},
hoveron='color', hoverinfo='count+probability',
labelfont={'size': 18, 'family': 'Times'},
tickfont={'size': 16, 'family': 'Times'},
arrangement='freeform')])
fig.show()
⑤go.FigureWidgetを使用した散布図+平行カテゴリ図
複雑なので説明は省略します。
使えそうな部分をピックアップして活用しましょう。
import ipywidgets as widgets
import pandas as pd
import numpy as np
cars_df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/imports-85.csv')
# Build parcats dimensions
categorical_dimensions = ['body-style', 'drive-wheels', 'fuel-type']
dimensions = [dict(values=cars_df[label], label=label) for label in categorical_dimensions]
# Build colorscale
color = np.zeros(len(cars_df), dtype='uint8')
colorscale = [[0, 'gray'], [0.33, 'gray'],
[0.33, 'firebrick'], [0.66, 'firebrick'],
[0.66, 'blue'], [1.0, 'blue']]
cmin = -0.5
cmax = 2.5
# Build figure as FigureWidget
fig = go.FigureWidget(
data=[go.Scatter(x=cars_df.horsepower, y=cars_df['highway-mpg'],
marker={'color': color, 'cmin': cmin, 'cmax': cmax,
'colorscale': colorscale, 'showscale': True,
'colorbar': {'tickvals': [0, 1, 2], 'ticktext': ['None', 'Red', 'Blue']}},
mode='markers'),
go.Parcats(domain={'y': [0, 0.4]}, dimensions=dimensions,
line={'colorscale': colorscale, 'cmin': cmin,
'cmax': cmax, 'color': color, 'shape': 'hspline'})]
)
fig.update_layout(height=800, xaxis={'title': 'Horsepower'},
yaxis={'title': 'MPG', 'domain': [0.6, 1]},
dragmode='lasso', hovermode='closest')
# Build color selection widget
color_toggle = widgets.ToggleButtons(
options=['None', 'Red', 'Blue'],
index=1, description='Brush Color:', disabled=False)
# Update color callback
def update_color(trace, points, state):
# Compute new color array
new_color = np.array(fig.data[0].marker.color)
new_color[points.point_inds] = color_toggle.index
with fig.batch_update():
# Update scatter color
fig.data[0].marker.color = new_color
# Update parcats colors
fig.data[1].line.color = new_color
# Register callback on scatter selection...
fig.data[0].on_selection(update_color)
# and parcats click
fig.data[1].on_click(update_color)
# Display figure
widgets.VBox([color_toggle, fig])
⑥px.parallel_coordinatesを使用した平行座標プロット
px.parallel_coordinates()で作成することができます。
color=で色による区別もできます。
import plotly.express as px
df = px.data.iris()
fig = px.parallel_coordinates(df, color="species_id",
dimensions=['sepal_width', 'sepal_length', 'petal_width',
'petal_length'],
color_continuous_scale=px.colors.diverging.Tealrose,
color_continuous_midpoint=2)
fig.show()
⑦go.Parcoordsを使用した平行座標プロット
最後も応用例です。
使えそうな部分をピックアップして活用しましょう。
import plotly.graph_objects as go
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/bcdunbar/datasets/master/parcoords_data.csv")
fig = go.Figure(data=
go.Parcoords(
line = dict(color = df['colorVal'],
colorscale = 'Electric',
showscale = True,
cmin = -4000,
cmax = -100),
dimensions = list([
dict(range = [32000,227900],
constraintrange = [100000,150000],
label = "Block Height", values = df['blockHeight']),
dict(range = [0,700000],
label = 'Block Width', values = df['blockWidth']),
dict(tickvals = [0,0.5,1,2,3],
ticktext = ['A','AB','B','Y','Z'],
label = 'Cyclinder Material', values = df['cycMaterial']),
dict(range = [-1,4],
tickvals = [0,1,2,3],
label = 'Block Material', values = df['blockMaterial']),
dict(range = [134,3154],
visible = True,
label = 'Total Weight', values = df['totalWeight']),
dict(range = [9,19984],
label = 'Assembly Penalty Wt', values = df['assemblyPW']),
dict(range = [49000,568000],
label = 'Height st Width', values = df['HstW'])])
)
)
fig.show()
Plotlyに関する書籍紹介
↓Plotlyについて学べる数少ない参考書です。