究極の可視化アシスタント

Ultimate Visualization Assistant

AIとの一夜が私のデータ可視化のアプローチを変えた方法

Photo by Simon Abrams on Unsplash

太陽が薄れ始め、街の灯りが輝きだすと、オフィスでの遅い夜が訪れることが避けられなくなってきました。時間との競争に身を投じていました。重要なセールスプレゼンテーションが目前に迫り、成功は未だ達成されていない要求にかかっていました。それは、新しいテレビの帰属モデルの基礎的な方法論を簡潔に伝える洞察に富んだデータ可視化です。

見せびらかすのに十分複雑でありながら、説明なしでほとんどの情報を伝えることができる簡単なものが必要でした。時間が刻々と迫る中で、これは簡単な課題ではありませんでした。幸いなことに、人工知能の光の道標である私の信頼できる新しいアシスタントChatGPTが、手元に用意されていました。その主な使命は、私の頭の中で概念に過ぎなかったデータを、魅力的な視覚的な物語に変えるための助けとなることです。それは、部屋の中で最もデータに興味を持たない人々でも魅了することができるものです。

ちょっとしたドラマチックな話かもしれませんが、私は少しピンチに追い込まれていました。セールスデッキには、弊社のデータベースで簡単に見つけることができなかった非常にシンプルな例が必要でした。そのため、創作のデータを使うことにしました。

頭の中では、表示したい内容がすでに明確に分かっていました。ウェブトラフィックの基準値、TV広告に続くウェブ応答の急増、そして基準値と急増の間の差を示す方法が必要でした。Matplotlibのチャートは学術論文では堅実ですが、複雑さと本当に派手さを兼ね備えたものを作り出すには非常に巧妙な手が必要です。一般的な外観と迅速なチャート作成のために、Power BIに頼ることがよくありますが、既存のデータがない場合にはゼロから作成するのには適していません。

私はPlotlyをしばらく使っていましたが、それは幸せなパートナーのように思えました。ただし、パッケージに自信がなかったため、ドキュメントやStack Overflowを時間をかけて熟読することなく、思考をコードに落とし込むことはできませんでした。時間が少なかったので、最初のプロンプトを開始しました。

TV広告放映後のウェブトラフィック応答を表示する可視化を作成しています。まず、30分の間にサイト訪問数の1分当たりのカウントとしてウェブトラフィックを表現することから始めましょう。最初の10分間は0から4のランダムな値にする必要があります。2番目の10分間は、右に偏ったヒストグラムに見えるように、4から20のランダムな値にする必要があります。最後の10分間は最初の10分間と同じです。このデータを作成し、Plotlyの折れ線グラフを使用してチャートを作成してください。

次のコードが返されました。私の編集はupdate_layout関数内でのみ行いました。

import numpy as npimport plotly.graph_objects as go# Set seed for reproducibilitynp.random.seed(42)# Create arrays with the specified distributionsfirst_ten = np.random.uniform(low=0, high=4, size=10)last_ten = np.random.uniform(low=0, high=4, size=10)middle_ten = np.random.gamma(shape=2, scale=2, size=10) + 4 # shift the gamma distribution# Combine the arraysmeasurements = np.concatenate((first_ten, middle_ten, last_ten))# Create x valuesx_values = np.arange(1, 31)# Create the line chartfig = go.Figure(    data=go.Scatter(        x=x_values,         y=measurements,         mode='lines+markers')    )fig.update_layout(    title='TV広告のウェブトラフィックへの影響',     xaxis_title='時間',     yaxis_title='1分あたりの訪問数',    width=1000,    height=600)fig.show()
Chart as generated by the prior code block

ここで既に感動していました。右に偏ったヒストグラムに似た外観の要求がこれほどうまく処理されるとは思っていませんでした。おそらく、近所のアフターワークセッションが終わる前に終わるかもしれません。

次に、ウェブトラフィックの基準値を表すものが必要でした。現実には、これは単純に移動中央値として表すことができますが、データの限られた長さではうまくいきません。代わりに、最初と最後の10個の観測値の中央値が適切なアイデアを伝えるでしょう。

まず、配列first_tenとlast_tenの結合した中央値を計算してください。計算された中央値を水平線としてプロットしてください。

import numpy as np
import plotly.graph_objects as go

# 再現性のためにシードを設定
np.random.seed(42)

# 指定した分布で配列を作成
first_ten = np.random.uniform(low=0, high=4, size=10)
last_ten = np.random.uniform(low=0, high=4, size=10)
middle_ten = np.random.gamma(shape=2, scale=2, size=10) + 4 # ガンマ分布をシフト

# 配列を結合
measurements = np.concatenate((first_ten, middle_ten, last_ten))

# xの値を作成
x_values = np.arange(1, 31)

# 結合した中央値を計算
combined_median = np.median(np.concatenate((first_ten, last_ten)))

# ラインチャートを作成
fig = go.Figure()

# ラインチャートを作成
fig = go.Figure(
    data=go.Scatter(
        x=x_values,
        y=measurements,
        mode='lines+markers'
    )
)

# 中央値のラインを追加
fig.add_trace(
    go.Scatter(
        x=x_values,
        y=[combined_median]*len(x_values),
        mode='lines',
        name='ベースライン',
        line=dict(color='firebrick', width=2, dash='dash')
    )
)

fig.update_layout(
    title='ウェブトラフィックへの広告の影響',
    xaxis_title='時間',
    yaxis_title='分あたりの訪問数',
    width=1000,
    height=600
)

fig.show()

次に、中央値のラインのトレース名を「Median」から「ベースライン」に変更しました。

上記のコードブロックから追加されたベースラインの定数ラインを含むグラフ

これで、マーケティングモデルに詳しい方には「リフト」というアイデアが伝わりますが、訓練されていない目には、より焦点を絞った要素が必要です。説明が必要ないほどビジュアルが効果的になります。この時点で不足している主要な要素は、ウェブトラフィックの急増の因果関係を示すチャート要素と、広告によって帰属されるトラフィックの量を伝える方法です。

まず、因果関係の要素から始めます。

データの10分目にテレビの広告が放送され、ウェブトラフィックが急増します。その広告がその急増の原因であることを伝えるために、どのようなチャート要素を提案しますか?

回答では、垂直線と注釈を提案し、コードの更新を提供しました。

import numpy as np
import plotly.graph_objects as go

# 再現性のためにシードを設定
np.random.seed(42)

# 指定した分布で配列を作成
first_ten = np.random.uniform(low=0, high=4, size=10)
last_ten = np.random.uniform(low=0, high=4, size=10)
middle_ten = np.random.gamma(shape=2, scale=2, size=10) + 4 # ガンマ分布をシフト

# 配列を結合
measurements = np.concatenate((first_ten, middle_ten, last_ten))

# xの値を作成
x_values = np.arange(1, 31)

# 結合した中央値を計算
combined_median = np.median(np.concatenate((first_ten, last_ten)))

# ラインチャートを作成
fig = go.Figure()

# 散布図を追加
fig.add_trace(
    go.Scatter(
        x=x_values,
        y=measurements,
        mode='lines+markers',
        name='ウェブトラフィック'
    )
)

# 中央値のラインを追加
fig.add_trace(
    go.Scatter(
        x=x_values,
        y=[combined_median]*len(x_values),
        mode='lines',
        name='ベースライン',
        line=dict(color='firebrick', width=2, dash='dash')
    )
)

# 10分目に垂直線を追加
fig.add_shape(
    type='line',
    x0=10, y0=0,
    x1=10, y1=max(measurements),
    line=dict(
        color="Purple",
        width=3,
        dash="dot",
    )
)

# テレビ広告を示す注釈を追加
fig.add_annotation(
    x=10,
    y=max(measurements),
    text="TV広告放送",
    showarrow=True,
    arrowhead=1,
    ax=-100,
    ay=-25,
    font=dict(
        size=16,
        color="Black"
    ),
)

fig.update_layout(
    title='ウェブトラフィックへの広告の影響',
    xaxis_title='時間',
    yaxis_title='分あたりの訪問数',
    width=1000,
    height=600
)

fig.show()

注釈のフォントサイズのみを変更しました。

上記のコードブロックからのチャート。TVの広告放送の定数ラインと注釈が追加されました。

今、私たちはスパイクの明確に定義された原因と発生地点を持っていました。チャートにはまだ、関連するトラフィックのボリュームを示すものが必要でした。私はこれについてすでに望んでいることを知っていました — ベースラインとウェブトラフィックの間の領域を「リフトウィンドウ」(10分間)の期間にわたって塗りつぶすことです。私はAIの同僚にこれを実装するように戻りました。

広告に起因するベースラインを上回るウェブトラフィックのボリュームを表示したいです。ベースラインのラインとウェブトラフィックのラインの間に緑色のシェーディングを追加してください。データの10分目から20分目の領域のみを塗りつぶしてください。また、塗りつぶし領域の凡例アイテムも追加してください。

import numpy as npimport plotly.graph_objects as go# Set seed for reproducibilitynp.random.seed(42)# Create arrays with the specified distributionsfirst_ten = np.random.uniform(low=0, high=4, size=10)last_ten = np.random.uniform(low=0, high=4, size=10)middle_ten = np.random.gamma(shape=2, scale=2, size=10) + 4 # shift the gamma distribution# Combine the arraysmeasurements = np.concatenate((first_ten, middle_ten, last_ten))# Create x valuesx_values = np.arange(1, 31)# Calculate combined mediancombined_median = np.median(np.concatenate((first_ten, last_ten)))# Create the line chartfig = go.Figure()# Add scatter plotfig.add_trace(    go.Scatter(        x=x_values,         y=measurements,         mode='lines+markers',         name='ウェブトラフィック'))# Add median linefig.add_trace(    go.Scatter(        x=x_values,         y=[combined_median]*len(x_values),         mode='lines',         name='ベースライン',         line=dict(color='firebrick', width=2, dash='dash')))# Add shaded region for the influence of the adfig.add_trace(    go.Scatter(        x=list(x_values[9:20]) + list(x_values[9:20])[::-1],         y=list([combined_median]*11) + list(measurements[9:20])[::-1],         fill='toself',         fillcolor='rgba(0,200,0,0.2)',         line=dict(width=0),         hoverinfo="skip",         showlegend=True,         name='広告の影響'))# Add vertical line at minute 10fig.add_shape(    type='line',    x0=10, y0=0,    x1=10, y1=max(measurements),    line=dict(        color="Purple",        width=3,        dash="dot",    ))# Add annotation to indicate TV spotfig.add_annotation(    x=10,    y=max(measurements),    text="TVの広告放送",    showarrow=True,    arrowhead=1,    ax=-100,    ay=-25,    font=dict(        size=16,        color="Black"    ),)fig.update_layout(    title='ウェブトラフィックへの広告の影響',    xaxis_title='時間',    yaxis_title='分あたりの訪問数',    width=1000,    height=600)fig.show()
上記のコードブロックからのチャート。広告の影響を表すシェーディングが追加されました

これは良い方向に進んでいると感じましたが、「伝えようとしていること」の「明確さ」にはまだ満足していませんでした。私は既に与えられたコードに基づいていくつかの追加を行いました。

リフトウィンドウの終了を示すために、一定の垂直線と注釈を追加し、広告放送とウィンドウの終了のラインの色をそれぞれ緑と赤に変更しました。また、他の一定の線とよりマッチするように、ベースラインの一定のラインを紫色に変更し、点線にスタイルを変更しました。

その後、最後の要素としてベースライン領域のシェーディングが欲しかったです。これまでの完璧なパフォーマンスに乗ることを望んで、これを私のアシスタントに任せました。

ベースライン領域全体に紫色のシェーディングを追加してください。ベースラインの定数水平線の下に「ベースライン」という注釈を15分に追加してください。

ここで、シェーディングの位置については座標や具体的な数字は参照していません。

import numpy as npimport plotly.graph_objects as go# 再現性のためにシードを設定np.random.seed(42)# 指定された分布で配列を作成first_ten = np.random.uniform(low=0, high=4, size=10)last_ten = np.random.uniform(low=0, high=4, size=10)middle_ten = np.random.gamma(shape=2, scale=2, size=10) + 4 # ガンマ分布をシフト# 配列を結合measurements = np.concatenate((first_ten, middle_ten, last_ten))# x値を作成x_values = np.arange(1, 31)# 結合した中央値を計算combined_median = np.median(np.concatenate((first_ten, last_ten)))# 折れ線グラフを作成fig = go.Figure()# ベースライン領域を追加fig.add_trace(    go.Scatter(        x=list(x_values) + list(x_values)[::-1],         y=[combined_median]*len(x_values) + [0]*len(x_values),         fill='toself',         fillcolor='rgba(128, 0, 128, 0.2)',         line=dict(width=0),         hoverinfo="skip",         showlegend=True,         name='ベースライン'))# 散布図を追加fig.add_trace(    go.Scatter(        x=x_values,         y=measurements,         mode='lines+markers',         name='ウェブトラフィック',        line=dict(color='#636EFA')))# 中央値の線を追加fig.add_trace(    go.Scatter(        x=x_values,         y=[combined_median]*len(x_values),         mode='lines',         name='中央値',         line=dict(color='Purple', width=2, dash='dash')))# 広告の影響のシェーディング領域を追加fig.add_trace(    go.Scatter(        x=list(x_values[9:20]) + list(x_values[9:20])[::-1],         y=list([combined_median]*11) + list(measurements[9:20])[::-1],         fill='toself',         fillcolor='rgba(0,200,0,0.2)',         line=dict(width=0),         hoverinfo="skip",         showlegend=True,         name='広告の影響'))# 10分の垂直線を追加fig.add_shape(    type='line',    x0=10, y0=0,    x1=10, y1=max(measurements),    line=dict(        color="Green",        width=3,        dash="dot",    ))# TVスポットを示す注釈を追加fig.add_annotation(    x=10,    y=max(measurements),    text="TV広告放映",    showarrow=True,    arrowhead=1,    ax=-100,    ay=-25,    font=dict(        size=16,        color="Green"    ),)# 20分の垂直線を追加fig.add_shape(    type='line',    x0=20, y0=0,    x1=20, y1=max(measurements),    line=dict(        color="Red",        width=3,        dash="dot",    ))# リフトウィンドウのカットオフを示す注釈を追加fig.add_annotation(    x=20,    y=max(measurements),    text="リフトウィンドウのカットオフ",    showarrow=True,    arrowhead=1,    ax=100,    ay=-25,    font=dict(        size=16,        color="Red"    ),)# リフトのための注釈を追加fig.add_annotation(    x=15,    y=combined_median + (max(measurements[9:20])-combined_median)/4,    text="広告によるリフト",    showarrow=False,    font=dict(        size=18,        color="Green"    ),)# ベースラインのための注釈を追加fig.add_annotation(    x=15,    y=combined_median/2,    text="ベースライン",    showarrow=False,    font=dict(        size=18,        color="Purple"    ),)fig.update_layout(    title='ウェブトラフィックへの広告の影響',    xaxis_title='時間',    yaxis_title='1分あたりの訪問数',    width=1000,    height=600)fig.show()
上記のコードブロックからのグラフ。ベースラインのシェーディング、カットオフライン、およびその他の注釈が追加されています

特定の値が与えられずにベースラインシェーディングリクエストがキャプチャされることは最高レベルであり、この時点で私は非常に感銘を受けました。可視化に満足して、チャートをプレゼンテーションにドロップし、Teamsのメッセージを送信し、ChatGPTのタブを見て、ラップトップを閉じました。片付けをしている最中に、アフターワークのグループチャットからの通知が携帯の画面に表示されました。

プレゼンテーションのメッセージを見ましたが、遅く出ると言っていたのでは?待ってるからビールを用意しておくよ。

乾杯、ChatGPT。

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