オレとChatGPT

AIとの会話記録

Pandas, Plotly, FRED Visualization

オレ

pandas_datareader を利用し、FREAD から NASDAQ 100 (NASDAQ100) と 米国の失業率 (UNRATE) と リセッション期間 (USREC) のデータを取得し、 plotly を使いNASDAQ 100と米国の失業率を同じグラフに描画し、リセッション期間の背景色を変える方法を教えて下さい。


Model: GPT-4

pandas_datareaderを利用してFREDからデータを取得し、plotlyを使って可視化することは可能です。しかし、FREDはNASDAQ 100のデータを提供していません。代わりにYahoo Financeから取得することが可能です。以下にその手順を示します。まず、必要なライブラリをインストールします。以下のコマンドを使ってください:

pip install pandas_datareader yfinance plotly

以下に指示されたタスクを実行するPythonのコードを示します:

import pandas as pd
import pandas_datareader.data as web
import yfinance as yf
import plotly.graph_objects as go
from datetime import datetime

# データ取得開始日
start = datetime(2010, 1, 1)

# FREDから失業率とリセッション期間のデータを取得
unrate = web.DataReader('UNRATE', 'fred', start)
usrec = web.DataReader('USREC', 'fred', start)

# Yahoo FinanceからNASDAQ 100のデータを取得
nasdaq = yf.download('^NDX', start=start)

# 月次のクローズ価格にリサンプリング
nasdaq_month = nasdaq['Close'].resample('M').last()

# データの結合
data = pd.concat([nasdaq_month, unrate, usrec], axis=1)
data.columns = ['NASDAQ100', 'UNRATE', 'USREC']

# Plotlyで可視化
fig = go.Figure()

# NASDAQ 100のプロット
fig.add_trace(go.Scatter(x=data.index, y=data['NASDAQ100'], mode='lines', name='NASDAQ 100'))

# 失業率のプロット (y軸を右側に配置)
fig.add_trace(go.Scatter(x=data.index, y=data['UNRATE'], mode='lines', name='Unemployment Rate', yaxis="y2"))

# リセッション期間の背景色を変更
for i in range(len(data['USREC'])):
    if data['USREC'][i] == 1:
        if i != 0 and data['USREC'][i-1] == 0:
            recession_start = data.index[i]
        elif i == len(data['USREC']) - 1 or data['USREC'][i+1] == 0:
            recession_end = data.index[i]
            fig.add_vrect(x0=recession_start, x1=recession_end, fillcolor="grey", opacity=0.2)

# レイアウトの調整
fig.update_layout(
    title='NASDAQ 100 vs Unemployment Rate',
    xaxis=dict(title='Date'),
    yaxis=dict(title='NASDAQ 100'),
    yaxis2=dict(title='Unemployment Rate', overlaying='y', side='right'),
)

fig.show()

注意点として、リセッション期間(USREC)のデータは1ヶ月ごとに1(リセッション)または0(非リセッション)を取ります。以上のコードでは、連続するリセッション期間を1つの領域と見なし、


オレ

Yahoo Finance からデータを取得するのは問題が多いので避けたいです。https://fred.stlouisfed.org/series/NASDAQ100 をみると FRED も NASDAQ100 のデータを提供しているように思えるのですが。


Model: GPT-4

すみません、その点は見落としていました。FREDがNASDAQ 100のデータを提供しているのであれば、そのデータを使用することが可能です。以下に、FREDからNASDAQ 100、失業率、リセッション期間のデータを取得し、plotlyで可視化するPythonのコードを示します。

import pandas as pd
import pandas_datareader.data as web
import plotly.graph_objects as go
from datetime import datetime

# データ取得開始日
start = datetime(2010, 1, 1)

# FREDからNASDAQ 100、失業率、リセッション期間のデータを取得
nasdaq = web.DataReader('NASDAQ100', 'fred', start)
unrate = web.DataReader('UNRATE', 'fred', start)
usrec = web.DataReader('USREC', 'fred', start)

# データの結合
data = pd.concat([nasdaq, unrate, usrec], axis=1)

# Plotlyで可視化
fig = go.Figure()

# NASDAQ 100のプロット
fig.add_trace(go.Scatter(x=data.index, y=data['NASDAQ100'], mode='lines', name='NASDAQ 100'))

# 失業率のプロット (y軸を右側に配置)
fig.add_trace(go.Scatter(x=data.index, y=data['UNRATE'], mode='lines', name='Unemployment Rate', yaxis="y2"))

# リセッション期間の背景色を変更
for i in range(len(data['USREC'])):
    if data['USREC'][i] == 1:
        if i != 0 and data['USREC'][i-1] == 0:
            recession_start = data.index[i]
        elif i == len(data['USREC']) - 1 or data['USREC'][i+1] == 0:
            recession_end = data.index[i]
            fig.add_vrect(x0=recession_start, x1=recession_end, fillcolor="grey", opacity=0.2)

# レイアウトの調整
fig.update_layout(
    title='NASDAQ 100 vs Unemployment Rate',
    xaxis=dict(title='Date'),
    yaxis=dict(title='NASDAQ 100'),
    yaxis2=dict(title='Unemployment Rate', overlaying='y', side='right'),
)

fig.show()

このコードは、指定した期間のNASDAQ 100、失業率、およびリセッション期間のデータを取得し、NASDAQ 100と失業率を同じグラフに描画します。リセッション期間には背景色が付けられています。


オレ

データは取得できているようですが、正しく描画できていません。これは夫々のデータのサンプル期間が違うために欠損値が生じていると思います。 データを結合しない方が良くないですか。


Model: GPT-4

ご指摘の通り、異なるデータソースから取得したデータのサンプル期間が異なる場合、データを結合すると一部の期間で欠損値が生じる可能性があります。これを解決するために、データを個別に取得し、プロットする際にそれぞれを独立したトレースとして扱うことが可能です。以下に、それぞれのデータを独立して取得し、プロットするPythonのコードを示します。

import pandas as pd
import pandas_datareader.data as web
import plotly.graph_objects as go
from datetime import datetime

# データ取得開始日
start = datetime(2010, 1, 1)

# FREDから各データを個別に取得
nasdaq = web.DataReader('NASDAQ100', 'fred', start)
unrate = web.DataReader('UNRATE', 'fred', start)
usrec = web.DataReader('USREC', 'fred', start)

# Plotlyで可視化
fig = go.Figure()

# NASDAQ 100のプロット
fig.add_trace(go.Scatter(x=nasdaq.index, y=nasdaq['NASDAQ100'], mode='lines', name='NASDAQ 100'))

# 失業率のプロット (y軸を右側に配置)
fig.add_trace(go.Scatter(x=unrate.index, y=unrate['UNRATE'], mode='lines', name='Unemployment Rate', yaxis="y2"))

# リセッション期間の背景色を変更
for i in range(len(usrec)):
    if usrec['USREC'].iloc[i] == 1:
        if i != 0 and usrec['USREC'].iloc[i-1] == 0:
            recession_start = usrec.index[i]
        elif i == len(usrec['USREC']) - 1 or usrec['USREC'].iloc[i+1] == 0:
            recession_end = usrec.index[i]
            fig.add_vrect(x0=recession_start, x1=recession_end, fillcolor="grey", opacity=0.2)

# レイアウトの調整
fig.update_layout(
    title='NASDAQ 100 vs Unemployment Rate',
    xaxis=dict(title='Date'),
    yaxis=dict(title='NASDAQ 100'),
    yaxis2=dict(title='Unemployment Rate', overlaying='y', side='right'),
)

fig.show()

このコードでは、それぞれのデータを独立して取得し、その後、それぞれを独立したトレースとしてプロットします。これにより、各データのサンプル期間が異なる場合でも、それぞれのデータを適切にプロットできます。


オレ

今回は正しく描画できているようですが、リセッション期間の処理に疑問があります。iは0から始まるので、それを考慮しないで i-1 をアクセスするのは正しくないと思います。


Model: GPT-4

ご指摘の通り、リストやデータフレームのインデックスは0から始まり、i-1をアクセスするときにiが0である場合、存在しないインデックスを参照する問題があります。これを解決するためには、iの値をチェックして、iが0でない場合のみi-1をアクセスするように修正する必要があります。以下に修正したコードを示します。

import pandas as pd
import pandas_datareader.data as web
import plotly.graph_objects as go
from datetime import datetime

# データ取得開始日
start = datetime(2010, 1, 1)

# FREDから各データを個別に取得
nasdaq = web.DataReader('NASDAQ100', 'fred', start)
unrate = web.DataReader('UNRATE', 'fred', start)
usrec = web.DataReader('USREC', 'fred', start)

# Plotlyで可視化
fig = go.Figure()

# NASDAQ 100のプロット
fig.add_trace(go.Scatter(x=nasdaq.index, y=nasdaq['NASDAQ100'], mode='lines', name='NASDAQ 100'))

# 失業率のプロット (y軸を右側に配置)
fig.add_trace(go.Scatter(x=unrate.index, y=unrate['UNRATE'], mode='lines', name='Unemployment Rate', yaxis="y2"))

# リセッション期間の背景色を変更
recession_start = None
for i in range(len(usrec)):
    if usrec['USREC'].iloc[i] == 1:
        if recession_start is None:  # リセッション開始
            recession_start = usrec.index[i]
        elif i == len(usrec['USREC']) - 1 or usrec['USREC'].iloc[i+1] == 0:  # リセッション終了
            recession_end = usrec.index[i]
            fig.add_vrect(x0=recession_start, x1=recession_end, fillcolor="grey", opacity=0.2)
            recession_start = None

# レイアウトの調整
fig.update_layout(
    title='NASDAQ 100 vs Unemployment Rate',
    xaxis=dict(title='Date'),
    yaxis=dict(title='NASDAQ 100'),
    yaxis2=dict(title='Unemployment Rate', overlaying='y', side='right'),
)

fig.show()

このコードでは、iが0であるときにi-1をアクセスする問題を修正しています。リセッション期間の開始を示すrecession_start変数を導入し、リセッションが開始したらその日付を保持し、リセッションが終了したらその期間をプロットに追加します。これにより、リセッション期間のプロットがより正確になります。


https://chat.openai.com/?model=gpt-4


感想

ploty は使った事がなかったので、参考になった。0から全部自分でコードを書くよりは早いと思う。今回は指示して修正させたが、ChatGPTが間違えた時は、指示して直させるよりは自分で修正した方が早いと思った。

Google Colab で実行した結果はこちら https://colab.research.google.com/drive/1enJowNogoAAKlISIGd8cBpvAmGhARfyG?usp=sharing