ウェブサイト検索

Python を使用したインタラクティブなデータ サイエンス アプリケーションの構築


Python を使用して、ユーザーが入力を渡し、取得してフィードバックを取得し、画像、ビデオ、オーディオなどのマルチメディア要素を利用できる、魅力的でインタラクティブなアプリケーションを構築します。

インタラクションとは接触がすべてであり、ユーザーにストーリーをどのように伝え、ユーザーがそれを理解し、どのように関与するかを意味します。人々は自分の目で物事を見ることを好み、対話できる投影を好みます。

インタラクティブ アプリケーションは、ユーザーを積極的に関与させるために構築されたコンピューター ソフトウェアです。これは、ユーザーがボタンをクリックしたり、テキストを入力したり、画面上でオブジェクトを移動したりすると、プログラムがそれらのアクションに反応することを示します。これは、ユーザーが行為を実行し、コンピューターが反応する対話のように見えます。

インタラクティブなアプリケーションは、これらの主要な機能、ユーザー入力 (ユーザーがデータまたはコマンドを入力できる場所)、フィードバック (これはユーザー入力の結果です)、およびマルチメディア要素 (アプリケーションの作成に使用される画像、ビデオ、オーディオなど) で構成されます。インタラクションがより魅力的になります)。

インタラクティブなアプリケーションの例としては、教育用ソフトウェア、ソーシャル メディア アプリケーション、コンピューター ビデオ ゲームなどがあります。インタラクティブではないコンピューター ソフトウェアの非常に良い例は、実行中にユーザーの操作を必要としないコンピューターのスクリーン セーバーです。

データ サイエンスにインタラクティブ性を提供するライブラリ

当時は、Flask を使用してデータ サイエンス アプリケーションを提示するか、HTML、CSS、JavaScript を学習する必要がありました。しかし現在、インタラクティブ データ サイエンス Web ライブラリの導入により、状況は大幅に改善され、簡単になりました。これらのフレームワークにより、データ サイエンティストは、フロントエンド テクノロジの学習、データ アプリケーションの共有、デプロイなどの手間をかけずに、インタラクティブ データ サイエンス アプリケーションを構築できる柔軟性が得られます。 Python プログラミング言語だけを使用してクラウド上のアプリケーションを構築できます。

これらのライブラリには次のようなものがあります。

  • ストリームライト
  • グラディオ
  • ダッシュ
  • パネル

ストリームライト

Streamlit は、わずか数行のコードで高度にインタラクティブなデータ アプリを構築するために使用されるオープンソースの Python フレームワークです。 2019 年に作成されたときの主な目的は、あなたにとって最も重要なこと、 つまりデータ分析に集中して集中できるようにすることでした。

Streamlit は、Python スクリプトを共有可能な Web アプリに変換することで機能します。 Streamlit のシンプルさが人気の理由です。 Streamlit ライブラリの使用はシンプルかつ迅速であるため、データ アプリを作成するために事前の Web プログラミング スキルは必要ありません。 Streamlit の詳細については、こちらをご覧ください。

Streamlit は優れたツールですが、その有用性は状況によって異なります。 Streamlit アプリのデザインと外観はかなり厳格であるため、HTML、JS、CSS を作成する準備ができていない限り、すべてのアプリケーションは同じレイアウトとスタイルになります。

グラディオ

Gradio は、機械学習 (ML) アプリケーションの作成を容易にするオープンソースの Web フレームワークです。これにより、開発者はフロントエンド コードの開発から解放され、ML モデルのインターフェイスを簡単に構築できるようになります。

開発者は Gradio を使用して、テキスト、グラフィック、またはオーディオベースのモデルのインターフェイスを構築します。 Gradio は、TensorFlow、PyTorch、Scikit-learn など、多くのよく知られた ML フレームワークもサポートしています。

Gradio は機械学習のデモンストレーションにより適していますが、Streamlit はデータ ダッシュボードの作成により重点を置いています。これが 2 つの言語の主な違いです。ドラッグ アンド ドロップ インターフェイスにより、カスタムの入力フィールドと出力の作成が簡単になり、機械学習モデルのホスティングと共有の統合サポートにより、展開プロセスが簡素化されます。

一部の Gradio アプリケーションはかなり古く、時代遅れに見える場合があります。したがって、カスタマイズするには基本的な CSS の書き方を知っておく必要があります。独立したアプリとしてパフォーマンスが向上する Streamlit アプリケーションとは異なり、Gradio アプリは別の Web ページに埋め込まれた場合に最適に機能します。

ダッシュ

Dash は、Python、R、または Julia を使用してデータ アプリケーションを作成するためのオープンソース フレームワークです。これは、データ駆動型のインタラクティブなダッシュボードを作成するための優れたツールであり、Python データ アプリケーションを迅速に開発するためのローコード フレームワークであるという利点があります。

Dash には、ユーザー インターフェイスを作成するための Python の HTML ラッパーが含まれていますが、これを使用するには HTML の知識が必要です。また、Streamlit は少し複雑であるため、Streamlit ほど簡単に始めることはできません (「コールバック」 といくつかの HTML を利用する必要があります)。

パネル

Panel は、Python だけを使用して強力なツール、ダッシュボード、複雑なアプリケーションを簡単に作成できるようにすることを目的としたオープンソースの Python ツールキットです。 Panel の広範なアプローチにより、PyData エコシステムに簡単に接続できると同時に、強力でインタラクティブなデータ テーブル、視覚化などを提供して、データのロックを解除、分析、共有し、生産的なワークフローでデータを共同作業できるようになります。

その機能セットには、低レベルのコールバック ベースの API と高レベルのリアクティブ API の両方が含まれており、対話性の高い複雑な複数ページのアプリを簡単に作成したり、探索的なアプリケーションを迅速に設計したりできます。

利用可能なすべてのソリューションと同様に、Panel を使用すると、アプリをローカルで簡単に実行およびホストできます。ただし、それらをクラウドにデプロイするのは自分自身です。彼らは、いくつかの展開の選択肢についての指示を提供します

Streamlit を使用したインタラクティブなデータ アプリの構築

このセクションでは、米国国勢調査局からの 2010 年から 2019 年の米国人口の視覚化とデータを表示する、完全に機能するインタラクティブなダッシュボードを構築します。

アプリケーションのデモは次のとおりです。

: アプリケーションをテストしたい場合は、ここで確認できますが、先に進んでコードを確認したい場合は、自由に実行してください。ここで確認してください

要件

  • Python 3.5以降
  • Streamlit pip install streamlit
  • Pandas - データ分析とラングリング用
  • Altair - これは Python 視覚化ライブラリです
  • Plotly Express - このライブラリは、Figure を作成するための高レベル API として使用されます。

データセット

ダッシュボードに使用される米国国勢調査局のデータセットには 3 つの重要な列 (州、年、人口) があり、指標の主な基礎として機能します。

以下の画像は、データセットがどのようなものかを示しています。

必要なライブラリをインポートする

import streamlit as st
import pandas as pd
import altair as alt
import plotly.express as px

ページの設定

次のステップでは、ブラウザに表示されるページのタイトルアイコンをアプリケーションに割り当てて、アプリケーションの設定を指定します。これは、サイドバーが拡大されたときにどのように表示されるか、およびページのコンテンツがページの幅に一致する広いレイアウトでどのように表示されるかを指定します。

Altair プロットのカラーテーマを調整して、アプリの暗い配色に合わせることができます。

st.set_page_config(
    page_title="USA Population Trends",
    page_icon="🇺🇸",
    layout="wide",
    initial_sidebar_state="expanded")

alt.themes.enable("dark")

データのインポート

Pandas を使用してデータセットをプロジェクトに読み込みます。

population_data = pd.read_csv('data/us-population-census-2010-2019.csv')

サイドバーの構成

st.title() を使用して、アプリのタイトルを構築します。 st.selectbox() を使用して、ユーザーが特定の年と色のテーマを選択できるドロップダウン ウィジェットを作成します。

その後、その年のデータは chosen_year を使用して (2010 年から 2019 年までのアクセス可能な年から) サブセット化され、アプリ内に表示されます。 chosen_palette を使用すると、ヒートマップコロプレス マップを、前述のウィジェットによって提供される色に従って色付けできます。

with st.sidebar:
    st.title('🇺🇸 USA Population Trends')
    
    available_years = list(population_data.year.unique())[::-1]
    
    chosen_year = st.selectbox('Choose a year', available_years)
    year_data = population_data[population_data.year == chosen_year]
    sorted_year_data = year_data.sort_values(by="population", ascending=False)

    palette_options = ['blues', 'greens', 'reds', 'purples', 'oranges', 'greys']
    chosen_palette = st.selectbox('Choose a color palette', palette_options)

プロットとチャートの種類

ヒートマップ、コロプレス マップ、ドーナツ チャートの 3 つのチャートを使用します。さまざまなプロットを表示するカスタム関数を定義してみましょう。

ヒートマップ

関数 create_heat_map() は、2010 年から 2019 年の米国人口のヒートマップを表示するために使用されます。

# Heatmap
def create_heat_map(data, y_axis, x_axis, color_var, color_scheme):
    heat_map = alt.Chart(data).mark_rect().encode(
            y=alt.Y(f'{y_axis}:O', axis=alt.Axis(title="Year", titleFontSize=18, titlePadding=15, titleFontWeight=900, labelAngle=0)),
            x=alt.X(f'{x_axis}:O', axis=alt.Axis(title="", titleFontSize=18, titlePadding=15, titleFontWeight=900)),
            color=alt.Color(f'max({color_var}):Q',
                             legend=None,
                             scale=alt.Scale(scheme=color_scheme)),
            stroke=alt.value('black'),
            strokeWidth=alt.value(0.25),
        ).properties(width=900
        ).configure_axis(
        labelFontSize=12,
        titleFontSize=12
        )
    # height=300
    return heat_map

出力は次のとおりです。

コロプレスの地図

関数 create_choropleth() は、選択した年の米国 52 州の色付き地図を表示します。

# Choropleth map
def create_choropleth(data, location_col, color_col, color_scheme):
    map_plot = px.choropleth(data, locations=location_col, color=color_col, locationmode="USA-states",
                               color_continuous_scale=color_scheme,
                               range_color=(0, max(year_data.population)),
                               scope="usa",
                               labels={'population':'Population'}
                              )
    map_plot.update_layout(
        template='plotly_dark',
        plot_bgcolor='rgba(0, 0, 0, 0)',
        paper_bgcolor='rgba(0, 0, 0, 0)',
        margin=dict(l=0, r=0, t=0, b=0),
        height=350
    )
    return map_plot

出力は次のとおりです。

ドーナツチャート

最後に作成するグラフはドーナツ グラフで、各州の人口移動の割合を示します。ドーナツのグラフィックを作成する前に、毎年の人口の移動を決定する必要があります。

# Donut chart
def create_donut(value, label, color):
    color_map = {
        'blue': ['#29b5e8', '#155F7A'],
        'green': ['#27AE60', '#12783D'],
        'red': ['#E74C3C', '#781F16'],
        'purple': ['#8E44AD', '#4A235A']
    }
    chart_colors = color_map.get(color, ['#F39C12', '#875A12'])
    
    data = pd.DataFrame({
        "Category": ['', label],
        "Percentage": [100-value, value]
    })
    background = pd.DataFrame({
        "Category": ['', label],
        "Percentage": [100, 0]
    })
    
    chart = alt.Chart(data).mark_arc(innerRadius=45, cornerRadius=25).encode(
        theta="Percentage",
        color= alt.Color("Category:N",
                        scale=alt.Scale(domain=[label, ''], range=chart_colors),
                        legend=None),
    ).properties(width=130, height=130)
    
    text = chart.mark_text(align='center', color="#29b5e8", font="Lato", fontSize=32, fontWeight=700, fontStyle="italic").encode(text=alt.value(f'{value} %'))
    background_chart = alt.Chart(background).mark_arc(innerRadius=45, cornerRadius=20).encode(
        theta="Percentage",
        color= alt.Color("Category:N",
                        scale=alt.Scale(domain=[label, ''], range=chart_colors),
                        legend=None),
    ).properties(width=130, height=130)
    return background_chart + chart + text

出力:

人口をテキストに変換

次のステップでは、母集団の値を凝縮するカスタム関数を開発します。特に、メトリクス カードの値の表示は 28,995,881 から、より管理しやすい 29.0 M に減りました。これは千の範囲内の数字にも当てはまります。

# Convert population to text 
def format_population(number):
    if number > 1000000:
        if not number % 1000000:
            return f'{number // 1000000} M'
        return f'{round(number / 1000000, 1)} M'
    return f'{number // 1000} K'

# Calculation year-over-year population migrations
def compute_population_change(data, target_year):
    current_year = data[data['year'] == target_year].reset_index()
    previous_year = data[data['year'] == target_year - 1].reset_index()
    current_year['population_change'] = current_year.population.sub(previous_year.population, fill_value=0)
    return pd.concat([current_year.states, current_year.id, current_year.population, current_year.population_change], axis=1).sort_values(by="population_change", ascending=False)

出力は次のとおりです。

アプリのレイアウトを定義する

すべての要素が準備できたので、アプリのレイアウトを定義して、それらをすべてアプリ内にまとめてみましょう。まず 3 つの列を作成します。

columns = st.columns((1.5, 4.5, 2), gap='medium')

入力引数 (1.5、4.5、2) は、2 番目の列が最も大きく、幅が最初の列の約 3 倍であることを示しています。

最初の列

この列には、選択した年のインバウンドおよびアウトバウンドの移動が最も多かった州を表示する指標カードが含まれます。この列には、州の流入と流出の両方の移行を示すドーナツ グラフも含まれています。

with columns[0]:
    st.markdown('#### Population Changes')

    population_change_data = compute_population_change(population_data, chosen_year)

    if chosen_year > 2010:
        top_state = population_change_data.states.iloc[0]
        top_state_pop = format_population(population_change_data.population.iloc[0])
        top_state_change = format_population(population_change_data.population_change.iloc[0])
        
        bottom_state = population_change_data.states.iloc[-1]
        bottom_state_pop = format_population(population_change_data.population.iloc[-1])   
        bottom_state_change = format_population(population_change_data.population_change.iloc[-1])   
    else:
        top_state = bottom_state = '-'
        top_state_pop = bottom_state_pop = '-'
        top_state_change = bottom_state_change = ''
    
    st.metric(label=top_state, value=top_state_pop, delta=top_state_change)
    st.metric(label=bottom_state, value=bottom_state_pop, delta=bottom_state_change)
    
    st.markdown('#### Migration Trends')

    if chosen_year > 2010:
        growing_states = population_change_data[population_change_data.population_change > 50000]
        shrinking_states = population_change_data[population_change_data.population_change < -50000]
        
        growth_percentage = round((len(growing_states)/population_change_data.states.nunique())*100)
        shrink_percentage = round((len(shrinking_states)/population_change_data.states.nunique())*100)
        growth_chart = create_donut(growth_percentage, 'Population Growth', 'green')
        shrink_chart = create_donut(shrink_percentage, 'Population Decline', 'red')
    else:
        growth_percentage = shrink_percentage = 0
        growth_chart = create_donut(growth_percentage, 'Population Growth', 'green')
        shrink_chart = create_donut(shrink_percentage, 'Population Decline', 'red')

    chart_columns = st.columns((0.2, 1, 0.2))
    with chart_columns[1]:
        st.write('Growth')
        st.altair_chart(growth_chart)
        st.write('Decline')
        st.altair_chart(shrink_chart)

2列目

2 番目の列は最大の列で、以前に作成したカスタム関数を使用してコロプレス マップとヒートマップを表示します。

with columns[1]:
    st.markdown('#### Total Population Distribution')
    
    choropleth = create_choropleth(year_data, 'states_code', 'population', chosen_palette)
    st.plotly_chart(choropleth, use_container_width=True)
    
    heat_map = create_heat_map(population_data, 'year', 'states', 'population', chosen_palette)
    st.altair_chart(heat_map, use_container_width=True)

3列目

3 番目の列には上位の州が表示され、人口は色付きの進行状況バーで表示されます。その下に about セクションも追加されます。

with columns[2]:
    st.markdown('#### State Rankings')

    st.dataframe(sorted_year_data,
                 column_order=("states", "population"),
                 hide_index=True,
                 width=None,
                 column_config={
                    "states": st.column_config.TextColumn(
                        "State",
                    ),
                    "population": st.column_config.ProgressColumn(
                        "Population",
                        format="%f",
                        min_value=0,
                        max_value=max(sorted_year_data.population),
                     )}
                 )
    
    with st.expander('Information', expanded=True):
        st.write('''
            - Data Source: [U.S. Census Bureau](https://www.census.gov/data/datasets/time-series/demo/popest/2010s-state-total.html)
            - :blue[**Population Changes**]: States with significant population increase/decrease for the selected year
            - :blue[**Migration Trends**]: Percentage of states with annual population change exceeding 50,000
            - Developed with Streamlit
            ''')

アプリケーションの実行

アプリケーションを実行するのは非常に簡単で、ターミナルに移動してプロジェクト フォルダー/ディレクトリに移動します。次のコマンドを実行します。

Streamlit run your_app_name.py

アプリはブラウザ ポート 8501 (http://localhost:8501/) で実行され、開きます。

アプリをデプロイする

アプリケーションの構築が正常に完了したら、次の手順に従ってアプリケーションをデプロイできます。

  1. アプリをパブリック GitHub リポジトリに公開し、requirements.txt ファイルがあることを確認します。
  2. share.streamlit.io にサインインし、GitHub に接続します
  3. [アプリのデプロイ] をクリックし、GitHub URL を貼り付けます。
  4. 「デプロイ」をクリックすると、アプリが数分以内に Streamlit Community Cloud にデプロイされます。
  5. デプロイしたアプリのリンクをコピーして、世界と共有します

結論

この記事は終わりまで来ました。ご覧のとおり、インタラクティブ データ アプリケーションはまったく新しいレベルに達し、データ アプリケーションにより多くのインタラクションと理解をもたらします。それらは興味深いことに魅力的で、聴衆を魅了します。

データ サイエンス アプリケーションに対話性を追加すればするほど、ユーザーはあなたが送信する価値をよりよく理解できるようになります。

さらに詳しく調べるには、次の役立つリソースを確認してください。

  • 合理化されたドキュメント
  • Streamlit でインタラクティブなデータ サイエンスを解き放つ
  • Streamlit 101: Python データ アプリの基礎

関連記事