Plotly Expressを用いて、可視化の様々な方法を学ぶ。

データの可視化

データの種類

  • 連続数値データ
  • カテゴリーデータ
    • 順序データ(ordinal data):順序づけが可能なもの.離散数値データもこれに含まれる.
    • 名義データ (nominal data):順序がつけられないもの.たとえば,性別(男女)や色など.
  • 時刻データ(の組)
  • 緯度・経度データ

データの種類を考えて、適切なグラフで描画する必要がある。

時刻データが1つの場合には,時系列解析

時刻データが2つ以上の場合には

  • ガントチャート(開始時刻と終了時刻)
  • 時空間ネットワーク(さらにモノの移動を考慮した場合)

緯度・経度データがあるなら,地図上に描画

以下のサイトFrom Data to Vizの決定木を参照

https://www.data-to-viz.com/

例題のデータ(Data Story)

https://github.com/holtzy/data_to_viz/tree/master/Example_dataset

Pandasでデータを読み込み、Plotly Express で描画する。

import pandas as pd
import plotly.express as px
from plotly.offline import plot as plt

# Google Colab.でプロットするためには,以下を実行する.
# import plotly.io as pio
# pio.renderers.default = "colab"

ヒストグラム

まずはヒストグラム(histgram, 度数分布表)を描画してみる.

ヒストグラムは数値データの分布の概要を知る際に便利である.

plotly.express (以下px)のhistgramを用いる.

主な引数

  • data_frame: データフレーム
  • x: $x$ 軸に用いる列名
  • color: 色に用いる列名
  • nbins: ビンの数(x軸の区分数)
  • marginal: 上部に表示する付加グラフの種類.'rug'(絨毯プロット), 'box'(箱ひげ図), 'violin'(バイオリンプロット), 'histogram'(ヒストグラム)から選択する.
  • opacity: 透過度
  • range_x: $x$ 軸の表示範囲
  • facet_row: 行に複数のグラフを表示させるときのカテゴリーデータが入っている列名
  • facet_column: 列に複数のグラフを表示させるときのカテゴリーデータが入っている列名

その他のグラフ

  • データそのものを見たい場合には絨毯プロット (rug)
  • データの大まかな値を見たい場合には箱ひげ図 (box)
  • 分布を見たい場合にはバイオリン図 (violin)

例題1. AIRBNB PRICES ON THE FRENCH RIVIERA

Air B&B社が提供している宿泊施設の価格データ

参照 https://www.data-to-viz.com/story/OneNum.html

df1 = pd.read_csv(
    "https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/1_OneNum.csv"
)
df1.head()
price
0 75.0
1 104.0
2 369.0
3 300.0
4 92.0
fig = px.histogram(
    df1, x="price", range_x=(0, 3000), nbins=1000, opacity=0.5, marginal="histogram"
)
# fig.show()#図を表示させる場合にはこの行を生かす。
# plt(fig); #JupyterLabの場合

問題(アヤメ)

アヤメのデータ(iris)を読み込み,アヤメの種類(3種)ごとのsepal_lengthのヒストグラムを描画せよ. (ヒント:横に並べるには facet_col引数に種類を表す列名を入れる.)

iris = px.data.iris()
iris.head()
sepal_length sepal_width petal_length petal_width species species_id
0 5.1 3.5 1.4 0.2 setosa 1
1 4.9 3.0 1.4 0.2 setosa 1
2 4.7 3.2 1.3 0.2 setosa 1
3 4.6 3.1 1.5 0.2 setosa 1
4 5.0 3.6 1.4 0.2 setosa 1

問題 (SAT,GPA)

http://logopt.com/data/SATGPA.csv データを読み込み,2種類のSATの成績とGPAのヒストグラムを描画せよ.

問題(ポケモン)

以下のように読み込んだポケモンのデータフレームを用いて,攻撃力(Attack),守備力(Defense)のヒストグラムを描画せよ.

pokemon = pd.read_csv("http://logopt.com/data/poke.csv", encoding="utf-8")
pokemon.head()
# Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed Generation Legendary Japanese
0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 45 1 False フシギダネ
1 2 Ivysaur Grass Poison 405 60 62 63 80 80 60 1 False フシギソウ
2 3 Venusaur Grass Poison 525 80 82 83 100 100 80 1 False フシギバナ
3 3 VenusaurMega Venusaur Grass Poison 625 80 100 123 122 120 80 1 False フシギバナ・メガ進化
4 4 Charmander Fire NaN 309 39 52 43 60 50 65 1 False ヒトカゲ

散布図

散布図(scatter plot)は,2つの数値データの関係を知る際に便利である.

Plotly Expressのpx.scatterを用いる.

主な引数

  • data_frame: データフレーム
  • x: $x$ 軸に用いる列名
  • y: $y$ 軸に用いる列名
  • color: 色に用いる列名
  • nbins: ビンの数(x軸の区分数)
  • marginal_x: $x$ 軸データを上部に表示させるグラフの種類.'rug', 'box', 'violin', 'histogram')から選択する.
  • marginal_y: $y$ 軸データを右部に表示させるグラフの種類.'rug', 'box', 'violin', 'histogram')から選択する.
  • animation_frame: 列の数値を元にアニメーションフレームを作成
  • animation_group: 列の要素ごとにアニメーションをグループ化
  • opacity: 透過度
  • range_x: $x$ 軸の表示範囲
  • facet_row: 行に複数のグラフを表示させるときのカテゴリーデータが入っている列名
  • facet_column: 列に複数のグラフを表示させるときのカテゴリーデータが入っている列名

例題2. APARTMENT PRICE VS GROUND LIVING AREA

価格と面積の関係を表すデータ

参照 https://www.data-to-viz.com/story/TwoNum.html

df2 = pd.read_csv(
    "https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/2_TwoNum.csv"
)
df2.head()
GrLivArea SalePrice
0 1710 208500
1 1262 181500
2 1786 223500
3 1717 140000
4 2198 250000
fig = px.scatter(
    df2, x="GrLivArea", y="SalePrice", marginal_y="rug", marginal_x="histogram"
)
# fig.show()
# plt(fig); #JupyterLabの場合

問題(アヤメ)

アヤメのデータを読み込み,'がく片長 'sepal_length'と花びら長 'petal_length'の関係を散布図を描け.

問題(ダイヤモンド)

http://logopt.com/data/Diamond.csv からダイアモンドの価格データを読み込み,カラット"carat"と価格 "price"] の散布図を描け.

問題 (SAT,GPA)

http://logopt.com/data/SATGPA.csv からデータを読み込み,MathSATとGPAの関係を描画せよ。

問題(ポケモン)

ポケモンのデータフレームに対して,攻撃力(Attack),守備力(Defense)の関係を散布図に描画せよ.

pokemon = pd.read_csv("http://logopt.com/data/poke.csv", encoding="utf-8")
pokemon.head()
# Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed Generation Legendary Japanese
0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 45 1 False フシギダネ
1 2 Ivysaur Grass Poison 405 60 62 63 80 80 60 1 False フシギソウ
2 3 Venusaur Grass Poison 525 80 82 83 100 100 80 1 False フシギバナ
3 3 VenusaurMega Venusaur Grass Poison 625 80 100 123 122 120 80 1 False フシギバナ・メガ進化
4 4 Charmander Fire NaN 309 39 52 43 60 50 65 1 False ヒトカゲ

問題(タイタニック)

titanicデータを読み込み,客室クラス(class)と性別(sex)ごとの運賃(fare)と生存確率(survived)の関係を描画せよ.

(ヒント:カテゴリーデータを行(列)に分けて並べるには facet_row(facet_col)引数に分けたい列名を入れる.)

import seaborn as sns

titanic = sns.load_dataset("titanic")
titanic.head()
survived pclass sex age sibsp parch fare embarked class who adult_male deck embark_town alive alone
0 0 3 male 22.0 1 0 7.2500 S Third man True NaN Southampton no False
1 1 1 female 38.0 1 0 71.2833 C First woman False C Cherbourg yes False
2 1 3 female 26.0 0 0 7.9250 S Third woman False NaN Southampton yes True
3 1 1 female 35.0 1 0 53.1000 S First woman False C Southampton yes False
4 0 3 male 35.0 0 0 8.0500 S Third man True NaN Southampton no True

問題 (チップ)

散布図では、引数trendlineに"ols"(ordinary least square)を指定することによって、最小2乗法による線形回帰の結果を表示することができる。

tipsデータを読み込み、以下の例では,tipsデータに対して支払総額('total_bill')とチップ('tip')の関係を, 行に喫煙者か否か(facet_row='smoker'),列に性別(facet_col='sex'),色に昼食か夕食か(color='time')を設定して分析せよ。

tips = sns.load_dataset("tips")
tips.head()
total_bill tip sex smoker day time size
0 16.99 1.01 Female No Sun Dinner 2
1 10.34 1.66 Male No Sun Dinner 3
2 21.01 3.50 Male No Sun Dinner 3
3 23.68 3.31 Male No Sun Dinner 2
4 24.59 3.61 Female No Sun Dinner 4

線グラフ

時系列データを描画するには、線グラフを用いる。

例題3. EVOLUTION OF THE BITCOIN PRICE

ビットコインの価格の推移

参照 https://www.data-to-viz.com/story/TwoNumOrdered.html

df3 = pd.read_csv(
    "https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/3_TwoNumOrdered.csv",
    sep=" ",
)
df3.head()
date value
0 2013-04-28 135.98
1 2013-04-29 147.49
2 2013-04-30 146.93
3 2013-05-01 139.89
4 2013-05-02 125.60
fig = px.line(df3, x="date", y="value")
# fig.show()
# plt(fig); #JupyterLabの場合

問題(航空機の乗客数)

http://logopt.com/data/AirPassengers.csv" からデータを読み込み、横軸にMonth、縦軸に#Passengersを設定して線グラフで描画せよ。

passengers = pd.read_csv("http://logopt.com/data/AirPassengers.csv")
passengers.head()
Month #Passengers
0 1949-01 112
1 1949-02 118
2 1949-03 132
3 1949-04 129
4 1949-05 121

散布図にさらなる軸を加えるには

散布図は2次元の情報を効率的に視覚化してくれる。 3次元以上の情報はどのように視覚化すべきか? 3軸目が連続量の場合には、3次元の散布図も考えられるが、大きさや色、もしくはアニメーションで視覚化した方がわかりやすい場合がある。

以下の例では、国別のGDP、平均寿命、人口のデータを可視化する。

例題4. LIFE EXPECTANCY, GDP PER CAPITA AND POPULATION SIZE

参照 https://www.data-to-viz.com/story/ThreeNum.html

print(px.data.gapminder.__doc__)
Each row represents a country on a given year.

https://www.gapminder.org/data/

Returns:
    A `pandas.DataFrame` with 1704 rows and the following columns:
    `['country', 'continent', 'year', 'lifeExp', 'pop', 'gdpPercap',
    'iso_alpha', 'iso_num']`.

df4 = px.data.gapminder()
df4.head()
country continent year lifeExp pop gdpPercap iso_alpha iso_num
0 Afghanistan Asia 1952 28.801 8425333 779.445314 AFG 4
1 Afghanistan Asia 1957 30.332 9240934 820.853030 AFG 4
2 Afghanistan Asia 1962 31.997 10267083 853.100710 AFG 4
3 Afghanistan Asia 1967 34.020 11537966 836.197138 AFG 4
4 Afghanistan Asia 1972 36.088 13079460 739.981106 AFG 4
fig = px.scatter(
    df4,
    x="gdpPercap",
    y="lifeExp",
    size="pop",
    color="continent",
    hover_name="country",
    animation_frame="year",
)
# fig.show()
# plt(fig); #JupyterLabの場合

問題(ポケモン)

以下のように読み込んだポケモンのデータフレームを用いて、自分で考えた(適当な列をx,y,size,color,animation_frameなどに設定し)散布図を描画せよ.

pokemon = pd.read_csv("http://logopt.com/data/poke.csv", encoding="utf-8")
pokemon.head()
# Name Type 1 Type 2 Total HP Attack Defense Sp. Atk Sp. Def Speed Generation Legendary Japanese
0 1 Bulbasaur Grass Poison 318 45 49 49 65 65 45 1 False フシギダネ
1 2 Ivysaur Grass Poison 405 60 62 63 80 80 60 1 False フシギソウ
2 3 Venusaur Grass Poison 525 80 82 83 100 100 80 1 False フシギバナ
3 3 VenusaurMega Venusaur Grass Poison 625 80 100 123 122 120 80 1 False フシギバナ・メガ進化
4 4 Charmander Fire NaN 309 39 52 43 60 50 65 1 False ヒトカゲ

特徴間の関係の図示

複数の特徴をもつデータが与えられたとき、特徴間の関係を一度に図示したいことがある。

以下の例題では、車の11つの特徴から連続量である6つの特徴を抽出し、その間の関係を図示する。同時に、1つのカテゴリーデータを色で区別する。

例題5. ELEVEN FEATURES FOR 32 CARS

参照: https://www.data-to-viz.com/story/SeveralNum.html

df5 = pd.read_csv(
    "https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/6_SeveralNum.csv"
)
df5.head()
Unnamed: 0 mpg cyl disp hp drat wt qsec vs am gear carb
0 Mazda RX4 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4
1 Mazda RX4 Wag 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4
2 Datsun 710 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1
3 Hornet 4 Drive 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1
4 Hornet Sportabout 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2
fig = px.scatter_matrix(
    df5, dimensions=["mpg", "disp", "drat", "hp", "qsec", "wt"], color="gear"
)
# fig.show()
# plt(fig); #JupyterLabの場合