ラグ変数×重回帰×信頼区間：時系列解析のビジュアルレシピ

# **user**:

ユーザは、時系列データを pandas dataframe 形式で与えます。データが新しい順に並んでいるのか、古い順に並んでいるのか、ユーザが指定します。ユーザは、目的変数の列ラベルを指定します。説明変数の列ラベルも複数指定します。次のような関数で、説明変数のラグ変数を作成します。各々の説明変数に対して、ラグを大きくしていった時に目的変数との相関がどう変化していくかを plotly の折れ線グラフで描画する関数を書いてください。ただし、折れ線グラフは各説明変数ごとに描いてください。

```python
def create_lagged_features(df, lag=3):
    df_lagged = df.copy()
    for i in range(1, lag + 1):
        df_lagged[f'X_lag{i}'] = df['X'].shift(i)
        df_lagged[f'Y_lag{i}'] = df['Y'].shift(i)
    return df_lagged.dropna()

df_lagged = create_lagged_features(df, lag=3)
```

# **assistant**:

以下に、指定された形式の `DataFrame` に対して、**各説明変数ごとにラグを取り、そのラグ変数と目的変数の相関係数を描画する**関数を提供します。

---

### ✅ 主な機能

* ユーザがデータの並び順（昇順 or 降順）を指定可能。
* 各説明変数について、指定したラグ数までの相関係数を算出。
* `plotly` を使って、各説明変数ごとにラグ vs 相関係数の折れ線グラフを描画。

---

### 🔧 関数コード

```python
import pandas as pd
import plotly.graph_objs as go
from plotly.subplots import make_subplots

def plot_lagged_correlations(df, 
                              target_col, 
                              feature_cols, 
                              lag=10, 
                              ascending=True):
    """
    各説明変数のラグと目的変数との相関を描画する

    Parameters:
    - df: pandas DataFrame（時系列データ）
    - target_col: 目的変数の列名（str）
    - feature_cols: 説明変数の列名リスト（List[str]）
    - lag: 最大ラグ数（int）
    - ascending: データの時系列順。True=古い順, False=新しい順（bool）
    """

    # 並び替え（古い順にする）
    df_sorted = df.sort_index(ascending=ascending).copy()

    fig = make_subplots(rows=len(feature_cols), cols=1, 
                        subplot_titles=[f"{col} vs {target_col}" for col in feature_cols],
                        vertical_spacing=0.1)

    for idx, feature in enumerate(feature_cols):
        correlations = []

        for l in range(1, lag + 1):
            df_lagged = df_sorted[[target_col, feature]].copy()
            df_lagged[f"{feature}_lag{l}"] = df_lagged[feature].shift(l)
            df_lagged = df_lagged.dropna()

            corr = df_lagged[target_col].corr(df_lagged[f"{feature}_lag{l}"])
            correlations.append(corr)

        trace = go.Scatter(x=list(range(1, lag + 1)),
                           y=correlations,
                           mode='lines+markers',
                           name=f"{feature} (lagged)",
                           line=dict(width=2))

        fig.add_trace(trace, row=idx + 1, col=1)

    fig.update_layout(
        height=300 * len(feature_cols),
        width=800,
        title_text="ラグ変数と目的変数との相関",
        showlegend=False
    )

    fig.update_xaxes(title_text="Lag")
    fig.update_yaxes(title_text="Correlation")

    fig.show()
```

---

### ✅ 使用例

```python
plot_lagged_correlations(
    df=my_dataframe,
    target_col="Y",
    feature_cols=["X1", "X2", "X3"],
    lag=20,
    ascending=True  # 古い順に並んでいるなら True、そうでなければ False
)
```

---

### 💡補足

* 相関は Pearson 相関を用いています。
* `df.sort_index()` でソートを行っていますが、インデックスが時系列である必要があります。もしそうでない場合は、`df.sort_values('日付列', ascending=True)` などに変更してください。
* `plotly` によりインタラクティブに可視化できます。

必要に応じて、`相関係数の絶対値` をプロットするようにも変更可能です。希望があればお知らせください。

# **user**:

ありがとうございます。上記のコードをベースに、次の変更を加えた全コードを書いてください。

・時系列ソートをするのではなく、入力に用いたデータをそのままの順序で用いるか、逆順で用いるかをユーザが選択する。
・Streamlitで表示できるようにする。

# **assistant**:

以下に、**ユーザがデータの順序（そのまま or 逆順）を選択できて、Streamlitで相関グラフを表示できるようにしたコード**を全体として提示します。

---

### ✅ 主な変更点

* データの並び順は、ソートではなく「そのまま」または「逆順」に変更するだけ。
* `plotly` を `Streamlit` 上に描画できるように調整（`st.plotly_chart`）。
* Streamlit UIから目的変数、説明変数、ラグ数、順序指定を選べる。

---

### ✅ 全コード（`streamlit_app.py` などで保存可能）

```python
import pandas as pd
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import streamlit as st

def plot_lagged_correlations(df, target_col, feature_cols, lag=10, use_reverse=False):
    """
    各説明変数のラグと目的変数との相関を描画するPlotlyグラフを返す。

    Parameters:
    - df: pandas DataFrame（時系列データ）
    - target_col: 目的変数の列名（str）
    - feature_cols: 説明変数の列名リスト（List[str]）
    - lag: 最大ラグ数（int）
    - use_reverse: データを逆順に使う（bool）

    Returns:
    - plotly.graph_objects.Figure
    """

    # 並び順の変更（ソートではなくreverse）
    df_used = df[::-1] if use_reverse else df.copy()

    fig = make_subplots(rows=len(feature_cols), cols=1, 
                        subplot_titles=[f"{col} vs {target_col}" for col in feature_cols],
                        vertical_spacing=0.1)

    for idx, feature in enumerate(feature_cols):
        correlations = []

        for l in range(1, lag + 1):
            df_lagged = df_used[[target_col, feature]].copy()
            df_lagged[f"{feature}_lag{l}"] = df_lagged[feature].shift(l)
            df_lagged = df_lagged.dropna()

            corr = df_lagged[target_col].corr(df_lagged[f"{feature}_lag{l}"])
            correlations.append(corr)

        trace = go.Scatter(
            x=list(range(1, lag + 1)),
            y=correlations,
            mode='lines+markers',
            name=f"{feature} (lagged)",
            line=dict(width=2)
        )

        fig.add_trace(trace, row=idx + 1, col=1)

    fig.update_layout(
        height=300 * len(feature_cols),
        width=800,
        title_text="ラグ変数と目的変数との相関",
        showlegend=False
    )

    fig.update_xaxes(title_text="Lag")
    fig.update_yaxes(title_text="Correlation")

    return fig


# Streamlit アプリ
st.title("ラグ変数と目的変数の相関可視化ツール")

# ファイルアップロード
uploaded_file = st.file_uploader("CSVファイルをアップロードしてください", type=["csv"])
if uploaded_file:
    df = pd.read_csv(uploaded_file)

    st.subheader("データプレビュー")
    st.dataframe(df.head())

    column_names = df.columns.tolist()

    target_col = st.selectbox("目的変数の列を選択", column_names)
    feature_cols = st.multiselect("説明変数の列を選択（複数可）", [col for col in column_names if col != target_col])

    lag = st.slider("最大ラグ数", min_value=1, max_value=50, value=10, step=1)
    order_choice = st.radio("データの並び順を選択", ["そのまま", "逆順"])
    use_reverse = (order_choice == "逆順")

    if st.button("相関を描画する") and feature_cols:
        fig = plot_lagged_correlations(df, target_col, feature_cols, lag=lag, use_reverse=use_reverse)
        st.plotly_chart(fig, use_container_width=True)
```

---

### ✅ 実行方法

1. 上記コードを `streamlit_app.py` などのファイルに保存。
2. ターミナルで以下を実行：

```bash
streamlit run streamlit_app.py
```

3. ブラウザが開き、CSVアップロード→変数選択→相関可視化が可能になります。

---

### ✅ 注意点

* アップロードするCSVファイルには、日付やインデックス列が含まれていてもOKですが、**順序はアップロード時のまま保持**されます（ソートしません）。
* 欠損値が多い場合はラグでデータが失われる点にご注意ください。

---

ご希望があれば、相関係数の絶対値でプロットする、相関値の表を出すなども追加できます。

# **user**:

ありがとうございます。目的変数自身のラグとの相関係数も合わせて計算できますか？

# **assistant**:

はい、**目的変数自身のラグとの相関係数（自己相関）も同時に計算・プロットすることは可能**です。

以下では、前回のコードを改良して、以下のように対応しています。

---

### ✅ 追加機能

* **目的変数自身のラグとの相関（自己相関）** を計算。
* グラフの最上段に **「自己相関（target lag）」** を追加表示。
* 他の説明変数と同様に、`plotly` グラフで可視化。

---

### ✅ 修正済みの全コード

```python
import pandas as pd
import plotly.graph_objs as go
from plotly.subplots import make_subplots
import streamlit as st

def plot_lagged_correlations(df, target_col, feature_cols, lag=10, use_reverse=False):
    """
    各説明変数および目的変数自身のラグと目的変数との相関を描画するPlotlyグラフを返す。
    """

    # 並び順の変更（reverse のみ）
    df_used = df[::-1] if use_reverse else df.copy()

    total_features = ["__SELF__"] + feature_cols  # 先頭に自己相関用プレースホルダ

    fig = make_subplots(
        rows=len(total_features), cols=1, 
        subplot_titles=["自己相関: " + target_col] + [f"{col} vs {target_col}" for col in feature_cols],
        vertical_spacing=0.1
    )

    for idx, feature in enumerate(total_features):
        correlations = []

        for l in range(1, lag + 1):
            df_lagged = df_used[[target_col]].copy()

            if feature == "__SELF__":
                # 自己相関（targetとそのラグ）
                df_lagged[f"{target_col}_lag{l}"] = df_lagged[target_col].shift(l)
                corr = df_lagged.dropna()[target_col].corr(df_lagged.dropna()[f"{target_col}_lag{l}"])
            else:
                df_lagged[feature] = df_used[feature]
                df_lagged[f"{feature}_lag{l}"] = df_lagged[feature].shift(l)
                corr = df_lagged.dropna()[target_col].corr(df_lagged.dropna()[f"{feature}_lag{l}"])

            correlations.append(corr)

        trace = go.Scatter(
            x=list(range(1, lag + 1)),
            y=correlations,
            mode='lines+markers',
            name=f"{feature} (lagged)" if feature != "__SELF__" else f"{target_col} (self lag)",
            line=dict(width=2)
        )

        fig.add_trace(trace, row=idx + 1, col=1)

    fig.update_layout(
        height=300 * len(total_features),
        width=800,
        title_text="ラグ変数と目的変数との相関（自己相関を含む）",
        showlegend=False
    )

    fig.update_xaxes(title_text="Lag")
    fig.update_yaxes(title_text="Correlation")

    return fig


# Streamlit アプリ
st.title("ラグ変数と目的変数の相関可視化ツール（自己相関も表示）")

# ファイルアップロード
uploaded_file = st.file_uploader("CSVファイルをアップロードしてください", type=["csv"])
if uploaded_file:
    df = pd.read_csv(uploaded_file)

    st.subheader("データプレビュー")
    st.dataframe(df.head())

    column_names = df.columns.tolist()

    target_col = st.selectbox("目的変数の列を選択", column_names)
    feature_cols = st.multiselect("説明変数の列を選択（複数可）", [col for col in column_names if col != target_col])

    lag = st.slider("最大ラグ数", min_value=1, max_value=50, value=10, step=1)
    order_choice = st.radio("データの並び順を選択", ["そのまま", "逆順"])
    use_reverse = (order_choice == "逆順")

    if st.button("相関を描画する") and feature_cols:
        fig = plot_lagged_correlations(df, target_col, feature_cols, lag=lag, use_reverse=use_reverse)
        st.plotly_chart(fig, use_container_width=True)
```

---

### ✅ 使い方のポイント

* 最上段に **目的変数自身のラグとの相関グラフ** が表示されます。
* 説明変数を選択していない場合はグラフは表示されません（必要に応じて変更可能）。
* CSVの行順が「新しい→古い」なら、「逆順」にチェックすることで正しくラグ関係を評価できます。

---

### ✅ 拡張案（必要であれば実装可）

* 相関係数の絶対値に切り替えるオプション
* 相関係数の表形式での表示
* グラフを PNG や PDF として保存

希望があればいつでもお知らせください！

# **user**:

ありがとうございます。それでは、時系列データを用いて、「過去のデータポイント（ラグ変数）を利用して（同時刻のデータポイントを利用せず）目的変数を重回帰して、標準重回帰係数を得る」関数のコードを書いてください。

# **assistant**:

こちらが、**ラグ変数のみを使って目的変数を重回帰し、標準化回帰係数（標準偏回帰係数）を求める関数**です。`sklearn` を使って標準化と回帰を行います。

---

### ✅ 概要

* 入力：

  * `df`: pandas DataFrame
  * `target_col`: 目的変数の列名（str）
  * `feature_cols`: 説明変数の列名（List\[str]）
  * `max_lag`: 各変数の最大ラグ数（int）
* 出力：

  * 回帰モデル（`LinearRegression`）
  * 標準化済み説明変数（`X`）
  * 目的変数（`y`）
  * 標準偏回帰係数の対応表（`pandas.Series`）

---

### ✅ コード

```python
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

def fit_lagged_standardized_regression(df, target_col, feature_cols, max_lag=5):
    """
    ラグ変数のみを使って目的変数を重回帰し、標準偏回帰係数を求める。

    Parameters:
    - df: pandas.DataFrame
    - target_col: str, 目的変数の列名
    - feature_cols: list of str, 説明変数の列名
    - max_lag: int, 各変数に対する最大ラグ数

    Returns:
    - model: sklearn.linear_model.LinearRegression オブジェクト
    - X_std: 標準化された説明変数（pd.DataFrame）
    - y_std: 標準化された目的変数（pd.Series）
    - standardized_coefficients: 標準偏回帰係数（pd.Series）
    """

    df_lagged = pd.DataFrame()

    # ラグ特徴量の作成
    for feature in feature_cols:
        for lag in range(1, max_lag + 1):
            df_lagged[f"{feature}_lag{lag}"] = df[feature].shift(lag)

    # 目的変数（将来の値）の調整
    df_lagged[target_col] = df[target_col]

    # 欠損を除去
    df_lagged = df_lagged.dropna()

    # 説明変数と目的変数
    X = df_lagged.drop(columns=[target_col])
    y = df_lagged[target_col]

    # 標準化
    scaler_X = StandardScaler()
    scaler_y = StandardScaler()

    X_std = pd.DataFrame(scaler_X.fit_transform(X), columns=X.columns, index=X.index)
    y_std = pd.Series(scaler_y.fit_transform(y.values.reshape(-1, 1)).flatten(), index=y.index)

    # 重回帰
    model = LinearRegression()
    model.fit(X_std, y_std)

    # 標準偏回帰係数
    standardized_coefficients = pd.Series(model.coef_, index=X.columns)

    return model, X_std, y_std, standardized_coefficients
```

---

### ✅ 使用例

```python
# 例：dfに "Y" を目的変数、["X1", "X2"] を説明変数として利用し、各ラグを1～5までとする
model, X_std, y_std, coeffs = fit_lagged_standardized_regression(df, target_col="Y", feature_cols=["X1", "X2"], max_lag=5)

# 結果確認
print(coeffs.sort_values(ascending=False))
```

---

### ✅ 補足

* この関数は**同時時点の説明変数（lag=0）を除外**します。
* `max_lag=5` の場合、各説明変数について 5 個のラグ特徴量が作成されます。
* 回帰係数は、スケールの異なる変数間で比較可能な **標準偏回帰係数**（すべてZスコア化したもの）です。
* 欠損値処理には `dropna()` を使っており、全ラグがそろう時点からのデータだけが使われます。

---

必要であれば、これを `Streamlit` 上で動かすコードもご提供できます。どうしましょうか？

# **user**:

はい、お願いします。ありがとうございます。

# **assistant**:

こちらが、先ほどの「ラグ変数による標準重回帰」の処理を **Streamlit アプリ**として実装した完全なコードです。
**CSVファイルのアップロード → ラグ回帰 → 標準偏回帰係数の表示**まで、GUIで実行できます。

---

## ✅ Streamlit アプリ：ラグ変数による標準回帰分析

```python
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

def fit_lagged_standardized_regression(df, target_col, feature_cols, max_lag=5, use_reverse=False):
    """
    ラグ変数だけを使って目的変数を重回帰し、標準偏回帰係数を求める。
    """
    if use_reverse:
        df = df[::-1]

    df_lagged = pd.DataFrame()

    # ラグ特徴量の作成
    for feature in feature_cols:
        for lag in range(1, max_lag + 1):
            df_lagged[f"{feature}_lag{lag}"] = df[feature].shift(lag)

    df_lagged[target_col] = df[target_col]

    df_lagged = df_lagged.dropna()

    X = df_lagged.drop(columns=[target_col])
    y = df_lagged[target_col]

    # 標準化
    scaler_X = StandardScaler()
    scaler_y = StandardScaler()

    X_std = pd.DataFrame(scaler_X.fit_transform(X), columns=X.columns, index=X.index)
    y_std = pd.Series(scaler_y.fit_transform(y.values.reshape(-1, 1)).flatten(), index=y.index)

    model = LinearRegression()
    model.fit(X_std, y_std)

    coeffs = pd.Series(model.coef_, index=X.columns)

    return model, X_std, y_std, coeffs


# ----------------------------
# Streamlit アプリ
# ----------------------------

st.title("📉 ラグ変数による標準回帰分析（標準偏回帰係数の取得）")

# CSVアップロード
uploaded_file = st.file_uploader("CSVファイルをアップロードしてください", type=["csv"])

if uploaded_file:
    df = pd.read_csv(uploaded_file)

    st.subheader("データプレビュー")
    st.dataframe(df.head())

    column_names = df.columns.tolist()

    # ユーザー入力
    target_col = st.selectbox("🎯 目的変数を選択してください", column_names)
    feature_cols = st.multiselect("📊 説明変数を選択してください（複数可）", [c for c in column_names if c != target_col])

    lag = st.slider("🔁 最大ラグ数を選んでください", min_value=1, max_value=50, value=5, step=1)
    order_choice = st.radio("📌 データの並び順", ["そのまま使う", "逆順にして使う"])
    use_reverse = order_choice == "逆順にして使う"

    if st.button("▶️ 回帰を実行"):
        if not feature_cols:
            st.warning("説明変数を1つ以上選択してください")
        else:
            model, X_std, y_std, coeffs = fit_lagged_standardized_regression(
                df, target_col, feature_cols, max_lag=lag, use_reverse=use_reverse
            )

            st.subheader("✅ 標準偏回帰係数（Standardized Coefficients）")
            coeffs_sorted = coeffs.sort_values(key=np.abs, ascending=False)
            st.dataframe(coeffs_sorted.rename("係数"))

            st.subheader("📈 回帰モデル情報")
            st.write("決定係数 R²: {:.4f}".format(model.score(X_std, y_std)))
```

---

## ✅ 主な特徴

* \*\*標準化済みの回帰係数（標準偏回帰係数）\*\*を出力。
* 各ラグの変数がどれだけ目的変数に寄与しているかを比較可能。
* **Streamlit GUI上で完結**：ファイル読み込み・ラグ数設定・並び順選択が可能。
* 決定係数 `R²` も表示され、モデルの当てはまりを確認できます。

---

## ✅ 拡張アイディア（必要であれば実装可）

* 回帰係数の棒グラフ表示（`plotly` などで可視化）
* 係数に対する有意性検定（statsmodels）
* ラグ変数の選択的削除（Lassoやステップワイズ回帰）
* 回帰結果の保存（CSV / Excel）

---

ご希望があれば、これらの機能追加もできますので、ぜひお知らせください！

# **user**:

ありがとうございます。上記コードをベースに、回帰係数の棒グラフ表示（plotlyで可視化）してください。９５％信頼区間もエラーバーとして表示してください。説明変数ごとに、横軸をラグ数にして、縦向きの棒グラフにしてください。値がマイナスの時は色を変えて下向きの棒グラフにしてください。

# **assistant**:

以下は、ご要望に応じて拡張した **完全な Streamlit アプリのコード**です：

---

## ✅ 追加機能

* **標準偏回帰係数を Plotly の棒グラフで可視化**
* **95%信頼区間（エラーバー）も表示**
* **ラグ数を横軸に、縦向き棒グラフで描画**
* **負の係数は赤、正の係数は青で表示**

---

## 🔧 Streamlit + Plotly 拡張コード

```python
import streamlit as st
import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler
import plotly.graph_objects as go
import statsmodels.api as sm

def fit_lagged_standardized_regression(df, target_col, feature_cols, max_lag=5, use_reverse=False):
    if use_reverse:
        df = df[::-1]

    df_lagged = pd.DataFrame()

    for feature in feature_cols:
        for lag in range(1, max_lag + 1):
            df_lagged[f"{feature}_lag{lag}"] = df[feature].shift(lag)

    df_lagged[target_col] = df[target_col]
    df_lagged = df_lagged.dropna()

    X = df_lagged.drop(columns=[target_col])
    y = df_lagged[target_col]

    # 標準化
    scaler_X = StandardScaler()
    scaler_y = StandardScaler()

    X_std = pd.DataFrame(scaler_X.fit_transform(X), columns=X.columns, index=X.index)
    y_std = pd.Series(scaler_y.fit_transform(y.values.reshape(-1, 1)).flatten(), index=y.index)

    # statsmodelsで信頼区間付き回帰
    X_std_sm = sm.add_constant(X_std)
    model = sm.OLS(y_std, X_std_sm).fit()

    coeffs = model.params.drop("const")
    conf_int = model.conf_int().drop("const")
    conf_int.columns = ["ci_lower", "ci_upper"]

    return coeffs, conf_int, model.rsquared


def plot_coefficients(coeffs, conf_int, feature_cols, max_lag):
    plots = []
    for feature in feature_cols:
        x = []
        y = []
        error_y = dict(type='data', symmetric=False, array=[], arrayminus=[])
        colors = []

        for lag in range(1, max_lag + 1):
            col_name = f"{feature}_lag{lag}"
            if col_name in coeffs.index:
                coef = coeffs[col_name]
                ci_low = conf_int.loc[col_name, "ci_lower"]
                ci_up = conf_int.loc[col_name, "ci_upper"]

                x.append(str(lag))
                y.append(coef)
                error_y["array"].append(ci_up - coef)
                error_y["arrayminus"].append(coef - ci_low)
                colors.append("blue" if coef >= 0 else "red")

        bar = go.Bar(
            x=x, y=y,
            name=feature,
            error_y=error_y,
            marker_color=colors,
        )

        layout = go.Layout(
            title=f"{feature} のラグと目的変数の標準偏回帰係数",
            xaxis_title="ラグ数",
            yaxis_title="標準偏回帰係数",
            height=500
        )
        fig = go.Figure(data=[bar], layout=layout)
        plots.append(fig)

    return plots


# ----------------------------
# Streamlit アプリ
# ----------------------------

st.title("📊 ラグ変数による標準回帰と係数の信頼区間付き可視化")

uploaded_file = st.file_uploader("CSVファイルをアップロードしてください", type=["csv"])

if uploaded_file:
    df = pd.read_csv(uploaded_file)

    st.subheader("データプレビュー")
    st.dataframe(df.head())

    column_names = df.columns.tolist()

    target_col = st.selectbox("🎯 目的変数を選択してください", column_names)
    feature_cols = st.multiselect("📊 説明変数を選択してください（複数可）", [c for c in column_names if c != target_col])

    lag = st.slider("🔁 最大ラグ数を選んでください", min_value=1, max_value=50, value=5, step=1)
    order_choice = st.radio("📌 データの並び順", ["そのまま使う", "逆順にして使う"])
    use_reverse = order_choice == "逆順にして使う"

    if st.button("▶️ 回帰を実行"):
        if not feature_cols:
            st.warning("説明変数を1つ以上選択してください")
        else:
            coeffs, conf_int, r2 = fit_lagged_standardized_regression(
                df, target_col, feature_cols, max_lag=lag, use_reverse=use_reverse
            )

            st.subheader("✅ 標準偏回帰係数")
            st.dataframe(pd.concat([coeffs.rename("係数"), conf_int], axis=1))

            st.markdown(f"**決定係数 R²:** `{r2:.4f}`")

            st.subheader("📊 ラグ別回帰係数の可視化（95%信頼区間付き）")

            figures = plot_coefficients(coeffs, conf_int, feature_cols, max_lag)
            for fig in figures:
                st.plotly_chart(fig, use_container_width=True)
```

---

## ✅ 実行環境の準備

### 必要なライブラリ：

```bash
pip install streamlit pandas scikit-learn plotly statsmodels
```

---

## ✅ 出力イメージ

* 各説明変数に対して：

  * 横軸：ラグ数（1, 2, ..., max\_lag）
  * 縦軸：標準偏回帰係数
  * 棒グラフ：青（正）、赤（負）
  * エラーバー：95%信頼区間（上下非対称）

---

ご要望に応じて、以下のような拡張も可能です：

* 回帰の **有意性フィルタリング（p値 < 0.05）**
* 複数ラグでの変数選択（Lasso, ステップワイズ）
* グラフの PDF / PNG / CSV ダウンロード機能

必要に応じてお知らせください！


# **user**:

ありがとうございます。ところで、次の関数は、リスト feature_cols に複数の feature_col があったときに、複数の feature_col に関する図を１つの図「fig」としてまとめて出力するコードです。この関数を改変して、リスト feature_cols に複数の feature_col があったときに、ひとつのfeature_colあたりひとつの図「fig」が入ってるリスト「figures」を返す関数にしてください。

```python
def plot_lagged_correlations(df, target_col, feature_cols, lag=10, use_reverse=False):
    """
    各説明変数および目的変数自身のラグと目的変数との相関を描画するPlotlyグラフを返す。
    """

    # 並び順の変更（reverse のみ）
    df_used = df[::-1] if use_reverse else df.copy()

    total_features = ["__SELF__"] + feature_cols  # 先頭に自己相関用プレースホルダ

    fig = make_subplots(
        rows=len(total_features),
        cols=1,
        subplot_titles=["自己相関: " + target_col]
        + [f"{col} vs {target_col}" for col in feature_cols],
        vertical_spacing=0.1,
    )

    for idx, feature in enumerate(total_features):
        correlations = []

        for l in range(1, lag + 1):
            df_lagged = df_used[[target_col]].copy()
            
            if feature == "__SELF__":
                # 自己相関（targetとそのラグ）
                df_lagged[f"{target_col}_lag{l}"] = df_lagged[target_col].shift(l)
                corr = df_lagged.dropna()[target_col].corr(
                    df_lagged.dropna()[f"{target_col}_lag{l}"]
                )
            else:
                df_lagged[feature] = df_used[feature]
                df_lagged[f"{feature}_lag{l}"] = df_lagged[feature].shift(l)
                corr = df_lagged.dropna()[target_col].corr(
                    df_lagged.dropna()[f"{feature}_lag{l}"]
                )

            correlations.append(corr)


        trace = go.Scatter(
            x=list(range(1, lag + 1)),
            y=correlations,
            mode="lines+markers",
            name=(
                f"{feature} (lagged)"
                if feature != "__SELF__"
                else f"{target_col} (self lag)"
            ),
            line=dict(width=2),
        )

        fig.add_trace(trace, row=idx + 1, col=1)

    fig.update_layout(
        height=300 * len(total_features),
        width=800,
        title_text="ラグ変数と目的変数との相関（自己相関を含む）",
        showlegend=False,
    )

    fig.update_xaxes(title_text="Lag")
    fig.update_yaxes(title_text="Correlation")

    return fig
```

# **assistant**:

以下は、あなたの既存の関数 `plot_lagged_correlations` を改変し、**各 `feature_col` ごとに個別の図 `fig` を生成し、それらをリスト `figures` として返す**関数です。

---

### ✅ 変更点：

* 1つの `feature_col` に対して1つの `fig` を作成
* `__SELF__`（目的変数自身のラグとの相関）も含めた各 `fig` を `figures` に格納
* `make_subplots` を使わず、1つの説明変数あたり単独の `plotly.graph_objects.Figure` を作成

---

### ✅ 新しい関数定義

```python
import pandas as pd
import plotly.graph_objects as go

def plot_lagged_correlations_separate(df, target_col, feature_cols, lag=10, use_reverse=False):
    """
    各説明変数および目的変数自身のラグと目的変数との相関を個別のPlotlyグラフとして返す。
    各説明変数ごとにfigが生成され、figuresリストとして返される。
    """
    df_used = df[::-1] if use_reverse else df.copy()
    figures = []

    # 目的変数自身の自己相関も最初に追加
    correlations = []
    for l in range(1, lag + 1):
        df_lagged = df_used[[target_col]].copy()
        df_lagged[f"{target_col}_lag{l}"] = df_lagged[target_col].shift(l)
        corr = df_lagged.dropna()[target_col].corr(df_lagged.dropna()[f"{target_col}_lag{l}"])
        correlations.append(corr)

    fig_self = go.Figure()
    fig_self.add_trace(go.Scatter(
        x=list(range(1, lag + 1)),
        y=correlations,
        mode="lines+markers",
        name=f"{target_col} (self lag)",
        line=dict(width=2),
    ))

    fig_self.update_layout(
        title=f"自己相関: {target_col}",
        xaxis_title="Lag",
        yaxis_title="Correlation",
        height=400,
        width=800
    )

    figures.append(fig_self)

    # 各説明変数ごとに個別のfigを生成
    for feature in feature_cols:
        correlations = []
        for l in range(1, lag + 1):
            df_lagged = df_used[[target_col]].copy()
            df_lagged[feature] = df_used[feature]
            df_lagged[f"{feature}_lag{l}"] = df_lagged[feature].shift(l)
            corr = df_lagged.dropna()[target_col].corr(df_lagged.dropna()[f"{feature}_lag{l}"])
            correlations.append(corr)

        fig = go.Figure()
        fig.add_trace(go.Scatter(
            x=list(range(1, lag + 1)),
            y=correlations,
            mode="lines+markers",
            name=f"{feature} (lagged)",
            line=dict(width=2),
        ))

        fig.update_layout(
            title=f"{feature} と {target_col} のラグ相関",
            xaxis_title="Lag",
            yaxis_title="Correlation",
            height=400,
            width=800
        )

        figures.append(fig)

    return figures
```

---

### ✅ 使用例（Streamlitなどで）

```python
figures = plot_lagged_correlations_separate(df, target_col, feature_cols, lag=10, use_reverse=False)

for fig in figures:
    st.plotly_chart(fig, use_container_width=True)
```

---

### ✅ 補足

* 最初の `figures[0]` は目的変数自身のラグ（自己相関）
* 以降の `figures[1:]` が各説明変数のラグとの相関
* 可視化を個別に表示することで見やすく、比較もしやすくなります

---

さらに棒グラフやヒートマップ形式に拡張することも可能です。必要でしたらご相談ください。

# **user**:

説明変数 X1, X2, … に対してラグ変数を作成し、目的変数に対する標準偏回帰係数の平均値と分散、９５％信頼区間に関する次のようなデータ形式の pandas dataframe があるとします。

```
                           mean    variance  ci_lower_95  ci_upper_95
X1_lag1  0.008234   34.533031   -13.414121     6.971943
X1_lag2  0.410974    4.525495    -4.420024     3.409460
X1_lag3  1.824117    1.877267    -0.973257     4.633143
X1_lag4  2.267675    1.104982     0.151261     4.814274
X1_lag5  2.395446    1.505850     0.859966     5.641305
```

偏回帰係数の棒グラフ表示（plotlyで可視化）してください。９５％信頼区間もエラーバーとして表示してください。説明変数ごとに個別に、横軸をラグ数にして、縦向きの棒グラフにしてください。値がマイナスの時は色を変えて下向きの棒グラフにしてください。

# **assistant**:

以下は、与えられた `pandas.DataFrame` 形式の統計量（`mean`, `variance`, `ci_lower_95`, `ci_upper_95`）を使って、**説明変数ごとにラグ数に対する標準偏回帰係数の棒グラフ**を描く Plotly コードです。

---

## ✅ 条件整理

* **入力形式**：

  * インデックスは `"X1_lag1"` のような形式（`変数名_lagN`）
  * 各列に `mean`, `variance`, `ci_lower_95`, `ci_upper_95`
* **要件**：

  * 横軸はラグ数、縦軸は偏回帰係数の平均（`mean`）
  * 95% 信頼区間をエラーバーで表示
  * プラスの棒は青、マイナスの棒は赤
  * 各変数ごとに個別のグラフ（Figure）を返す

---

## ✅ 実装コード

```python
import pandas as pd
import plotly.graph_objects as go
import re

def plot_regression_coefficients(df_stats):
    """
    各説明変数ごとのラグ付き標準偏回帰係数（平均値）の棒グラフを、
    95% 信頼区間エラーバー付きでプロットする。
    変数ごとに個別のグラフを返す。
    """
    # インデックスから 'X1_lag1' → ('X1', 1) のように分解
    df_stats = df_stats.copy()
    df_stats["variable"] = df_stats.index.map(lambda x: re.match(r"(.*)_lag(\d+)", x).group(1))
    df_stats["lag"] = df_stats.index.map(lambda x: int(re.match(r"(.*)_lag(\d+)", x).group(2)))

    figures = []

    for var in df_stats["variable"].unique():
        df_var = df_stats[df_stats["variable"] == var].sort_values("lag")

        bar_colors = ["blue" if m >= 0 else "red" for m in df_var["mean"]]

        fig = go.Figure()

        fig.add_trace(go.Bar(
            x=df_var["lag"],
            y=df_var["mean"],
            error_y=dict(
                type="data",
                symmetric=False,
                array=df_var["ci_upper_95"] - df_var["mean"],
                arrayminus=df_var["mean"] - df_var["ci_lower_95"],
                thickness=1.5,
                width=5,
                color="gray"
            ),
            marker_color=bar_colors,
        ))

        fig.update_layout(
            title=f"{var} のラグ付き標準偏回帰係数",
            xaxis_title="Lag",
            yaxis_title="Standardized Coefficient",
            height=400,
            width=800
        )

        figures.append(fig)

    return figures
```

---

## ✅ 使い方（Streamlit例）

```python
figures = plot_regression_coefficients(df_stats)

for fig in figures:
    st.plotly_chart(fig, use_container_width=True)
```

---

## ✅ 補足

* 色は `mean` が正か負かで分岐
* 信頼区間は非対称エラーバーとして描画
* 横軸は `lag`（数値型）なので棒の順序も自動で整います

---

ご希望があれば、この棒グラフをまとめて1つにすることや、凡例・注釈の追加なども対応可能です。

# **user**:

ありがとうございます。今日はこれで大丈夫です。今日の会話をブログに記録したいので、タイトル案をいくつか提示していただけますか？

# **assistant**:

こちらこそ、ありがとうございました！
本日の内容をもとに、ブログにふさわしいタイトル案をいくつかご提案します。テーマは「時系列データのラグ解析」「偏回帰係数の可視化」「StreamlitとPlotlyによるインタラクティブ分析」などに基づいています。

---

### ✅ タイトル案（汎用系・全体まとめ）

1. **「時系列データのラグ解析を徹底可視化！Plotly×Streamlitで見る相関と回帰の変化」**
2. **「ラグ付き回帰分析を可視化してみた：時系列×Plotly×Streamlit 実践ノート」**
3. **「目的変数と説明変数のラグ関係を調べ尽くす！インタラクティブ分析のすすめ」**
4. **「ラグ変数でわかる時系列の因果っぽさ：Plotly で見える化しよう」**
5. **「標準偏回帰係数の変化を可視化してわかる！時系列データの深掘り分析」**

---

### ✅ 特化型タイトル案（可視化や重回帰に焦点）

6. **「Plotly で見るラグ変数の影響力：重回帰×信頼区間×インタラクティブグラフ」**
7. **「ラグごとの偏回帰係数を棒グラフで！時系列分析のビジュアル攻略法」**
8. **「ラグ変数×重回帰×信頼区間：時系列解析のビジュアルレシピ」**
9. **「ラグ変数の回帰係数を色で魅せる：赤と青の可視化術」**
10. **「目的変数を過去から予測する：Streamlitで作るラグ付き回帰分析ダッシュボード」**

---

ご希望のトーン（学術寄り／エンジニア向け／初心者向け／キャッチーなタイトルなど）に合わせて調整も可能ですので、必要があればお気軽にお知らせください。

# **user**:

「ラグ変数×重回帰×信頼区間：時系列解析のビジュアルレシピ」で行きたいと思います。まとめを詳しく書いてください。

# **assistant**:

了解しました！以下に、ブログ記事「**ラグ変数×重回帰×信頼区間：時系列解析のビジュアルレシピ**」のための詳しいまとめ（本文構成例）をご提案します。適宜調整してご利用ください。

---

# ラグ変数×重回帰×信頼区間：時系列解析のビジュアルレシピ

## はじめに

時系列データを分析する上で、「過去の情報（ラグ）」が現在の状態や未来の予測にどれほど寄与しているのかを把握することは非常に重要です。本記事では、ラグ変数を活用した重回帰分析を中心に、以下の視点から解説と可視化を行います。

* 説明変数のラグと目的変数との相関
* 過去のデータのみを使った重回帰による影響力の可視化
* 回帰係数の信頼区間を含む棒グラフによるビジュアル解析

すべての解析は、**pandas**、**scikit-learn**、**plotly**、そして **Streamlit** を用いてインタラクティブに実施可能です。

---

## 1. ラグ変数の作成と時系列の順序指定

ユーザーがアップロードした時系列データをそのまま使うか、逆順（古い→新しい）にするかを選択できるようにしました。これは、モデルが時間の流れに基づいて構築されるか否かを制御するための柔軟性を持たせたものです。

```python
df_used = df[::-1] if use_reverse else df.copy()
```

---

## 2. 説明変数のラグと目的変数との相関

説明変数（例: X1, X2）のラグ変数を1からN（例: 10）まで作成し、目的変数との相関係数を計算・可視化しました。自己相関（目的変数自身のラグとの相関）も同時に表示できます。

* 各説明変数ごとに独立した相関グラフ（Plotly）を生成
* Lagごとの相関係数を折れ線グラフで描画

---

## 3. ラグ変数を使った重回帰分析

ラグ変数だけを用いて目的変数を予測する多変量線形回帰モデルを構築します。現在時点の説明変数の値は使わず、**過去の情報だけ**を使って予測するのがポイントです。

* 説明変数の各ラグを特徴量に展開
* scikit-learn による重回帰
* 標準偏回帰係数へのスケーリング（StandardScaler使用）

---

## 4. 偏回帰係数と信頼区間の可視化

各ラグごとの偏回帰係数の平均・分散・95％信頼区間を算出し、**Plotlyで棒グラフ**として可視化しました。

* 横軸：ラグ数（lag1, lag2, …）
* 縦軸：偏回帰係数（標準化済）
* 信頼区間：±1.96 \* 標準誤差
* 正の係数→青、負の係数→赤（色で視覚的に区別）

```python
# カスタムルールで色分け
color = 'blue' if mean > 0 else 'red'
```

---

## 5. Streamlitでの実装とインタラクティブ性

本記事の全機能は、**Streamlit** アプリとして構築可能です。以下の操作がGUIで行えます。

* 目的変数・説明変数の選択
* 時系列順序の指定（そのまま or 逆順）
* ラグ数の指定
* グラフの自動更新

---

## おわりに

時系列データの深掘りには、ラグ変数を用いた相関・回帰の分析が非常に有効です。特に、偏回帰係数に信頼区間を加えることで、どのラグが統計的に有意であるかの判断も可能になります。

インタラクティブな可視化と柔軟なデータ操作を組み合わせることで、より深い洞察と直感的な理解が得られます。今後はこの基盤をもとに、**因果推論**や\*\*時系列予測モデル（例：VARやARIMA）\*\*にも展開していけるでしょう。

---

必要に応じて、コード断片やStreamlitのUIのスクリーンショットを挿入すると、より魅力的な記事になります。さらに詳細な記事構成や追記が必要であれば、お気軽にお知らせください！


# **user**:

ありがとうございました。今後もよろしくお願いします！

# **assistant**:

こちらこそ、ありがとうございました！
いつでもお気軽にご相談ください。
時系列解析でも、因果推論でも、Streamlitアプリの構築でも、全力でサポートします！

今後とも、どうぞよろしくお願いいたします 😊📊💻