PythonとDashを使用してダッシュボードを作成する

PythonとDashでダッシュボードを作成する

 

イントロダクション

 

データサイエンスと分析の領域では、データの力は洞察を抽出するだけでなく、これらの洞察を効果的に伝えることで解放されます。これがデータ可視化が重要となるポイントです。

   

データ可視化は情報やデータのグラフィカルな表現です。チャート、グラフ、マップなどの視覚的な要素を使用して、生データのパターン、トレンド、外れ値をより簡単に把握することができます。データサイエンティストやアナリストにとって、データ可視化はデータをより迅速かつ正確に理解するための必須ツールであり、データを用いたストーリーテリングをサポートし、データに基づいた意思決定を支援します。

この記事では、Netflixのコンテンツの配信と分類を可視化するために、PythonとDashフレームワークを使用してダッシュボードを作成する方法を学びます。

   

Dashとは何ですか?

 

Dashは、純粋なPythonで分析的なWebアプリケーションを作成するためにPlotlyが開発したオープンソースの低コードフレームワークです。従来、そのような目的のためには、バックエンド(Python)とフロントエンド(JavaScript、HTML)の両方の技術に精通している必要があり、JavaScriptとHTMLを使用する必要がありました。

しかし、Dashはこのギャップを埋め、データサイエンティストやアナリストがPythonだけを使用してインタラクティブで美しいダッシュボードを作成できるようにします。このような低コード開発の側面が、特にPythonに慣れている人々にとって、分析用ダッシュボードを作成するための適切な選択肢となります。

 

データセットの分析

 

Dashに慣れ親しんだので、実践的なプロジェクトを始めましょう。Netflixの映画とテレビ番組のデータセットを使用します。このデータセットはKaggleで提供されており、Shivam Bansalによって作成されました。

このデータセットには、2021年現在のNetflixで利用可能な映画とテレビ番組の詳細が含まれており、コンテンツの種類、タイトル、監督、キャスト、製作国、公開年、評価、時間などが含まれています。

このデータセットは2021年に作成されましたが、メディアエンターテイメントのトレンドを理解し、データ可視化のスキルを開発するための貴重なリソースです。

このデータセットを使用して、次のポイントを可視化するダッシュボードを作成します:

  1. 地理的なコンテンツの分布:異なる国でのコンテンツ制作の変化を示すマップグラフ。
  2. コンテンツの分類:この可視化により、Netflixのコンテンツをテレビ番組と映画に分けて、どのジャンルが最も目立っているかを確認できます。

 

プロジェクトのワークスペースの設定

 

プロジェクトのためにnetflix-dashboardというディレクトリを作成し、次のコマンドでPythonの仮想環境を初期化してアクティブ化します:

# Linux & MacOS
mkdir netflix-dashboard && cd netflix-dashboard
python3 -m venv netflix-venv && source netflix-venv/bin/activate

 

# Windows Powershell
mkdir netflix-dashboard && cd netflix-dashboard
python -m venv netflix-venv && .\netflix-venv\Scripts\activate

 

次に、いくつかの外部パッケージをインストールする必要があります。データ操作にはpandasを使用し、ダッシュボード作成にはdash、グラフ作成にはplotly、ダッシュボードにスタイルを追加するためにdash-bootstrap-componentsを使用します:

# Linux & MacOS
pip3 install pandas dash plotly dash-bootstrap-components

 

# Windows Powershell
pip install pandas dash plotly dash-bootstrap-components

 

データセットのクリーニング

 

Netflixのデータセットを調べると、directorcastcountryの列に欠損値があります。また、date_addedの列のstring値を解析しやすいようにdatetimeに変換することも便利です。

データセットをクリーニングするために、以下のコードを含む新しいファイルclean_netflix_dataset.pyを作成し、それを実行します:

import pandas as pd

# データセットを読み込む
df = pd.read_csv('netflix_titles.csv')

# 欠損値を埋める
df['director'].fillna('ディレクターなし', inplace=True)
df['cast'].fillna('キャストなし', inplace=True)
df['country'].fillna('国なし', inplace=True)

# 欠損値と重複値を削除する
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)

# `date_added`列から余分な空白を削除し、値を`datetime`に変換する
df['date_added'] = pd.to_datetime(df['date_added'].str.strip())

# クリーニングしたデータセットを保存する
df.to_csv('netflix_titles.csv', index=False)

 

Dashの始め方

 

ワークスペースが設定され、データセットがクリーニングされたので、ダッシュボードの作業を開始する準備が整いました。以下のコードを含む新しいファイルapp.pyを作成します:

from dash import Dash, dash_table, html
import pandas as pd

# Dashアプリを初期化する
app = Dash(__name__)

# アプリのレイアウトを定義する
app.layout = html.Div([
        html.H1('Netflixの映画とテレビ番組のダッシュボード'),
        html.Hr(),
])

# ローカル開発モードでDashアプリを起動する
if __name__ == '__main__':
    app.run_server(debug=True)

 

app.py内のコードを解説してみましょう:

  • app = Dash(__name__):この行は新しいDashアプリを初期化します。これはアプリケーションの基盤と考えてください。
  • app.layout = html.Div(…)app.layout属性を使用すると、アプリケーションのユーザーインターフェースをデザインするためにHTMLのようなコードを記述できます。上記のレイアウトでは、ダッシュボードのタイトルにhtml.H1(…)見出し要素を使用し、タイトルの下に水平ルールhtml.Hr()要素を使用しています。
  • app.run(debug=True):この行は開発サーバーを起動し、Dashアプリをローカル開発モードで提供します。Dashは、軽量なWebサーバーフレームワークであるFlaskを使用して、アプリケーションをWebブラウザに提供します。

app.pyを実行すると、ターミナルにDashアプリが実行中であり、http://127.0.0.1:8050/でアクセス可能であることを示すメッセージが表示されます。このURLをWebブラウザで開いて表示できます:

   

結果は非常にシンプルですね。心配しないでください!このセクションでは、最も基本的なDashアプリの構造とコンポーネントを紹介することを目的としています。後でさらに機能やコンポーネントを追加して素晴らしいダッシュボードにします!

 

Dash Bootstrap Componentsの組み込み

 

次のステップは、ダッシュボードのレイアウトのコードを記述し、スタイルを追加することです!これには、Dash Bootstrap Components (DBC)を使用できます。これはDash用のBootstrapコンポーネントを提供するライブラリであり、レスポンシブなレイアウトでスタイル付けされたアプリを開発できます。

ダッシュボードはタブレイアウトでスタイル付けされ、同じスペース内でさまざまなタイプの情報をコンパクトに組織する方法を提供します。各タブは異なる可視化に対応します。

app.pyの内容を変更してDBCを組み込むことにしましょう:

from dash import Dash,dcc, html
import pandas as pd
import dash_bootstrap_components as dbc

# Dashアプリを初期化し、ダッシュボードにスタイルを適用するためにBootstrapテーマをインポートする
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        dcc.Store(id='store'),
        html.H1('Netflixの映画とテレビ番組のダッシュボード'),
        html.Hr(),
        dbc.Tabs(
            [
                dbc.Tab(label='地理的なコンテンツの分布', tab_id='tab1'),
                dbc.Tab(label='コンテンツの分類', tab_id='tab2'),
            ],
            id='tabs',
            active_tab='tab1',
        ),
        html.Div(id='tab-content', className='p-4'),
    ]
)

if __name__ == '__main__':
    app.run(debug=True)

 

この変更されたレイアウトでは、新しいコンポーネントが表示されます:

  • dbc.Container:トップレベルのコンポーネントとしてdbc.Containerを使用すると、レスポンシブで柔軟なコンテナでダッシュボードのレイアウト全体を包み込むことができます。
  • dcc.Store:このDash Coreコンポーネントは、データをクライアント側(ユーザーのブラウザ上)に保存することができ、データをローカルに保持することでアプリケーションのパフォーマンスを向上させることができます。
  • dbc.Tabs および dbc.Tab:各dbc.Tabは個別のタブを表し、異なる可視化を含むことができます。 label プロパティはタブ自体に表示される内容であり、 tab_id はタブを識別するために使用されます。 dbc.Tabsの active_tab プロパティは、Dashアプリが起動したときにアクティブなタブを指定するために使用されます。

今度は app.py を実行してください。その結果、ダッシュボードにはBootstrapスタイルのレイアウトが適用され、空のタブが2つ表示されます:

   

よくやりました!ついにダッシュボードに可視化を追加する準備が整いました。

 

コールバックと可視化の追加

 

Dashを使用する場合、相互作用性はコールバック関数を介して実現されます。コールバック関数は、入力プロパティが変更されたときに自動的に呼び出される関数です。それが「コールバック」と呼ばれるのは、アプリケーションで変更が発生するたびにDashによって「呼び戻される」関数であるためです。

このダッシュボードでは、選択したタブに関連する可視化を表示するためにコールバックを使用し、各可視化はプロジェクト構造の整理とモジュール化のために、新しい components ディレクトリの下に独自のPythonファイルに保存されます。

 

地理的なコンテンツ分布の可視化

 

新しいディレクトリcomponentsを作成し、その中に地理的_content.pyというファイルを作成します。このファイルは、年ごとにNetflixのコンテンツ制作がどのように国によって異なるかを示すコロプレスマップを生成します:

import pandas as pd
import plotly.express as px
from dash import dcc, html

df = pd.read_csv('netflix_titles.csv')

# 国の情報がないエントリをフィルタリングし、複数の製作国がある場合は、最初の国を製作国として扱います
df['country'] = df['country'].str.split(',').apply(lambda x: x[0].strip() if isinstance(x, list) else None)

# date_added列から年を抽出します
df['year_added'] = pd.to_datetime(df['date_added']).dt.year
df = df.dropna(subset=['country', 'year_added'])

# 各国ごとの各年のコンテンツの数を計算します
df_counts = df.groupby(['country', 'year_added']).size().reset_index(name='count')

# アニメーションフレームが昇順になるようにDataFrameを'sort_values'でソートします
df_counts = df_counts.sort_values('year_added')

# 年ごとの各タイプのコンテンツの数を計算し、欠落しているタイプ-年のペアにゼロを埋めます
df_year_counts = df.groupby(['year_added', 'type']).size().reset_index(name='count')

# plotly expressを使用して折れ線グラフを作成します
fig2 = px.line(df_year_counts, x='year_added', y='count', color='type',
               title='Content distribution by type over the years',
               markers=True, color_discrete_map={'Movie': 'dodgerblue', 'TV Show': 'darkblue'})
fig2.update_traces(marker=dict(size=12))
fig2.update_layout(width=1280, height=720, title_x=0.5)

layout = html.Div([
    dcc.Graph(figure=fig1),
    html.Hr(),
    dcc.Graph(figure=fig2)
])

上記のコードは、データを'country''year_added'でフィルタリングおよびグループ化し、df_countsのデータフレーム内の各国と各年ごとのコンテンツの数を計算します。

次に、px.choropleth関数は、df_countsのデータフレームの列を引数の値として使用して、マップグラフを作成します:

  • locations='country':’country’列に含まれる地理的な位置値を指定することができます。
  • locationmode='country names':この引数は、提供されたlocationsが国名であることを「関数に伝えます」。Plotly ExpressはISO-3国コードや米国の州など、他の位置モードもサポートしています。
  • color='count':マップを彩るために使用される数値データを指定するために使用されます。ここでは、各国と各年ごとのコンテンツの数を示す'count'列を指します。
  • color_continuous_scale='YlGnBu'colorで指定された列に数値データが含まれている場合、各国のために連続的なカラースケールを作成します。
  • animation_frame='year_added':この引数は、'year_added'列上でアニメーションを作成します。マップグラフに年ごとのアニメーションを追加し、各国のコンテンツ生産の進化を年ごとに表示することができます。
  • projection='natural earth':この引数は、df_countsのデータフレームから列を使用しません。ただし、地球の世界地図で投影を設定するために'natural earth'の値が必要です。

そして、コロプレスマップの直下には、年ごとにカテゴリ別(TV番組または映画)のコンテンツ量の変化を示すマーカー付きの折れ線グラフが含まれています。

折れ線グラフを生成するために、新しいデータフレームdf_year_countsが作成されます。このデータフレームは、元のdfデータを'year_added''type'の列でグループ化し、各組み合わせごとのコンテンツ数を集計します。

このグループ化されたデータは、px.lineで使用され、'x''y'の引数はそれぞれ'year_added''count'の列に割り当てられ、'color'の引数は'type'に設定され、TV番組と映画を区別します。

 

コンテンツの分類の可視化

 

次のステップは、タイプとジャンルの観点からNetflixのコンテンツを可視化するためにツリーマップグラフを生成するcontent_classification.pyという新しいファイルを作成することです:

import pandas as pd
import plotly.express as px
from dash import dcc, html

df = pd.read_csv('netflix_titles.csv')

# listed_in列を分割して複数のジャンルを処理するためにexplodeを使用する
df['listed_in'] = df['listed_in'].str.split(', ')
df = df.explode('listed_in')

# タイプとジャンルの各組み合わせの数を計算する
df_counts = df.groupby(['type', 'listed_in']).size().reset_index(name='count')

fig = px.treemap(df_counts, path=['type', 'listed_in'], values='count', color='count',
                 color_continuous_scale='Ice', title='タイプとジャンル別のコンテンツ')

fig.update_layout(width=1280, height=960, title_x=0.5)
fig.update_traces(textinfo='label+percent entry', textfont_size=14)

layout = html.Div([
    dcc.Graph(figure=fig),
])

 

上記のコードでは、データを読み込んだ後、'listed_in'列を調整して複数のジャンルのコンテンツを処理するために、ジャンルを分割して展開し、各コンテンツごとにジャンルごとに新しい行を作成します。

次に、df_countsデータフレームを作成して、データを'type''listed_in'の列でグループ化し、各タイプ-ジャンルの組み合わせの数を計算します。

その後、df_counts DataFrameの列は次のようにpx.treemap 関数の引数の値として使用されます:

  • path=['type', 'listed_in']:これらはツリーマップで表される階層的なカテゴリです。 'type''listed_in' の列には、コンテンツの種類(テレビ番組または映画)とジャンルが含まれています。
  • values='count':ツリーマップ内の各長方形のサイズは、各種類-ジャンルの組み合わせごとのコンテンツ量を表す 'count' 列に対応しています。
  • color='count':ツリーマップ内の長方形の色付けには 'count' 列も使用されます。
  • color_continous_scale='Ice'color によって示される列に数値データが含まれる場合、ツリーマップ内の各長方形に連続的なカラースケールを構築します。

新しい2つの可視化ファイルを作成した後、現在のプロジェクトの構造は次のようになります:

netflix-dashboard
├── app.py
├── clean_netflix_dataset.py
├── components
│   ├── content_classification.py
│   └── geographical_content.py
├── netflix-venv
│   ├── bin
│   ├── etc
│   ├── include
│   ├── lib
│   ├── pyvenv.cfg
│   └── share
└── netflix_titles.csv

コールバックの実装

最後のステップは、app.pyを変更して、componentsディレクトリ内の2つの新しい可視化をインポートし、タブを選択したときにグラフをレンダリングするためのコールバック関数を実装することです:

from dash import Dash, dcc, html, Input, Output
import dash_bootstrap_components as dbc
from components import (
    geographical_content,
    content_classification
)

app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        dcc.Store(id='store'),
        html.H1('Netflix Movies and TV Shows Dashboard'),
        html.Hr(),
        dbc.Tabs(
            [
                dbc.Tab(label='Geographical content distribution', tab_id='tab1'),
                dbc.Tab(label='Content classification', tab_id='tab2'),
            ],
            id='tabs',
            active_tab='tab1',
        ),
        html.Div(id='tab-content', className='p-4'),
    ]
)


# このコールバック関数は、ユーザーの選択に基づいてダッシュボード内のタブを切り替えます。
# 'tab-content' コンポーネントを新しく選択されたタブのレイアウトで更新します。
@app.callback(Output('tab-content', 'children'), [Input('tabs', 'active_tab')])
def switch_tab(at):
    if at == 'tab1':
        return geographical_content.layout
    elif at == 'tab2':
        return content_classification.layout


if __name__ == '__main__':
    app.run(debug=True)

コールバックデコレータ @app.callback は、'tabs' コンポーネントの 'active_tab' プロパティの変更を監視し、Input オブジェクトで表されます。

'active_tab' が変更されるたびに、switch_tab 関数がトリガーされます。この関数は 'active_tab' のIDをチェックし、Output オブジェクトによって示される 'tab-content' Div にレンダリングする対応するレイアウトを返します。したがって、タブを切り替えると関連する可視化が表示されます。

最後に、app.pyを再度実行して、新しい可視化が追加されたダッシュボードを表示します:

   

まとめ

この記事では、Netflixのコンテンツの分布と分類を探索および可視化するためのダッシュボードの作成方法を学びました。PythonとDashのパワーを活用することで、独自の可視化を作成し、データに対する貴重な洞察を提供する準備が整いました。

このプロジェクトの完全なコードは、次のGitHubリポジトリで確認できます:https://github.com/gutyoh/netflix-dashboard

この記事が役に立った場合、Pythonとデータサイエンスに関する知識をさらに拡大したい場合は、Hyperskillのデータサイエンス入門トラックをチェックしてみてください。

もしこのブログに関する質問やフィードバックがありましたら、以下のコメント欄でお知らせください。

Hermann Rösch は、HyperskillのGoプログラミングトラックの技術著者であり、EdTechへの情熱を駆使して次世代のソフトウェアエンジニアをエンパワーしています。同時に、イリノイ大学アーバナ・シャンペーン校の修士課程生としてデータの世界に没頭しています。

オリジナル。許可を得て再掲載。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

データサイエンス

「Seerの最高データオフィサーであるDr. Serafim Batzoglouによるインタビューシリーズ」

セラフィム・バツォグルはSeerのチーフデータオフィサーですSeerに加わる前は、セラフィムはInsitroのチーフデータオフィサー...

人工知能

「ジャスティン・マクギル、Content at Scaleの創設者兼CEO - インタビューシリーズ」

ジャスティンは2008年以来、起業家、イノベーター、マーケターとして活動しています彼は15年以上にわたりSEOマーケティングを...

人工知能

「トリントの創設者兼CEO、ジェフ・コフマンへのインタビューシリーズ」

ジェフ・コーフマンは、ABC、CBS、CBCニュースで30年のキャリアを持った後、Trintの創設者兼CEOとなりましたジェフは手作業の...

人工知能

「ジンディのCEO兼共同創設者、セリーナ・リー― インタビューシリーズ」

「Celina Leeは、ZindiのCEO兼共同創設者であり、アフリカのデータサイエンティスト向けの最大の専門ネットワークです Celina...

データサイエンス

「3つの質問:ロボットの認識とマッピングの研磨」

MIT LIDSのLuca CarloneさんとJonathan Howさんは、将来のロボットが環境をどのように知覚し、相互作用するかについて議論し...

人工知能

「15Rockの共同創業者兼CEO、ガウタム・バクシ氏によるインタビューシリーズ」

「ガウタム・バクシは、気候リスク管理とアドバイザリーサービスのグローバルリーダーである15Rockの共同創設者兼CEOですガウ...