You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何逐次计算状态转移概率?(基于Pandas的0-1序列分析)

解决方案

步骤1:生成5步区间窗口

根据需求,我们需要生成对应试次区间来逐次计算转移概率。这里提供两种常见的区间生成方式:

  • 非重叠窗口:每5个试次为一个独立窗口,覆盖全部40次试次(前4个窗口属于Block1,后4个属于Block2)
    window_size = 5
    # 生成区间:(0,5), (5,10), ..., (35,40)
    trial_ranges = [(i, i+window_size) for i in range(0, len(sc), window_size)]
    
  • 滑动窗口:每次移动1个试次,生成更精细的连续窗口,适合观察细微趋势变化
    window_size = 5
    trial_ranges = [(i, i+window_size) for i in range(len(sc) - window_size + 1)]
    

步骤2:优化转移概率计算

原有的计算函数可以用Pandas的crosstab简化,更高效且易维护:

import pandas as pd

def transition_matrix(transitions):
    # 生成连续状态转移对
    pairs = pd.DataFrame({
        'from': transitions[:-1],
        'to': transitions[1:]
    })
    # 计算归一化的转移矩阵(行求和为1)
    mat = pd.crosstab(pairs['from'], pairs['to'], normalize='index')
    # 确保4种转移类型都存在(避免部分窗口缺失对应转移的情况)
    mat = mat.reindex(index=[0,1], columns=[0,1], fill_value=0)
    return mat.values

步骤3:逐次计算并可视化趋势

方式1:多窗口热图对比

适合非重叠窗口的直观对比,清晰展示每个窗口的转移概率分布:

import matplotlib.pyplot as plt
import seaborn as sns

fig, axes = plt.subplots(2, 4, figsize=(16, 8))
axes = axes.flatten()

for i, (start, end) in enumerate(trial_ranges):
    sub_sc = sc[start:end]
    trans_mat = transition_matrix(sub_sc)
    
    sns.heatmap(trans_mat, annot=True, fmt=".2f", cmap="YlGnBu", ax=axes[i], cbar=False)
    axes[i].set_xlabel('目标状态')
    axes[i].set_ylabel('起始状态')
    # 标记所属Block
    block = 1 if end <=20 else 2
    axes[i].set_title(f'窗口 {start+1}-{end}\nBlock {block}')

plt.tight_layout()
plt.show()

方式2:折线图展示趋势变化

更直观观察从Block1到Block2的4种转移概率的连续变化趋势:

# 存储所有窗口的转移概率结果
results = []
for start, end in trial_ranges:
    sub_sc = sc[start:end]
    trans_mat = transition_matrix(sub_sc)
    results.append({
        'window_start': start+1,
        'window_end': end,
        'block': 1 if end <=20 else 2,
        '0→0': trans_mat[0][0],
        '0→1': trans_mat[0][1],
        '1→0': trans_mat[1][0],
        '1→1': trans_mat[1][1]
    })

# 转换为DataFrame用于绘图
trend_df = pd.DataFrame(results)

plt.figure(figsize=(12,6))
sns.lineplot(data=trend_df, x='window_start', y='0→0', label='0→0', marker='o')
sns.lineplot(data=trend_df, x='window_start', y='0→1', label='0→1', marker='s')
sns.lineplot(data=trend_df, x='window_start', y='1→0', label='1→0', marker='^')
sns.lineplot(data=trend_df, x='window_start', y='1→1', label='1→1', marker='*')

# 标记Block1和Block2的分界
plt.axvline(x=20, color='r', linestyle='--', label='Block 1/2 分界')
plt.xlabel('窗口起始试次')
plt.ylabel('转移概率')
plt.title('从Block1到Block2的转移概率趋势')
plt.legend()
plt.grid(True)
plt.show()

完整可运行代码示例

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# 初始化40次试次数据
df = pd.DataFrame()
df['response'] = [0,1,1,0,1,0,1,0,1,0,1,1,1,1,1,0,0,1,1,0,
                  1,0,0,1,1,1,0,0,0,1,0,1,1,0,0,1,1,0,0,1]
sc = df['response'].tolist()
sc = [x for x in sc if not np.isnan(x)]

def transition_matrix(transitions):
    pairs = pd.DataFrame({
        'from': transitions[:-1],
        'to': transitions[1:]
    })
    mat = pd.crosstab(pairs['from'], pairs['to'], normalize='index')
    mat = mat.reindex(index=[0,1], columns=[0,1], fill_value=0)
    return mat.values

# 生成非重叠5步窗口
window_size = 5
trial_ranges = [(i, i+window_size) for i in range(0, len(sc), window_size)]

# 生成趋势折线图
results = []
for start, end in trial_ranges:
    sub_sc = sc[start:end]
    trans_mat = transition_matrix(sub_sc)
    results.append({
        'window_start': start+1,
        'window_end': end,
        'block': 1 if end <=20 else 2,
        '0→0': trans_mat[0][0],
        '0→1': trans_mat[0][1],
        '1→0': trans_mat[1][0],
        '1→1': trans_mat[1][1]
    })

trend_df = pd.DataFrame(results)

plt.figure(figsize=(12,6))
sns.lineplot(data=trend_df, x='window_start', y='0→0', label='0→0', marker='o')
sns.lineplot(data=trend_df, x='window_start', y='0→1', label='0→1', marker='s')
sns.lineplot(data=trend_df, x='window_start', y='1→0', label='1→0', marker='^')
sns.lineplot(data=trend_df, x='window_start', y='1→1', label='1→1', marker='*')

plt.axvline(x=20, color='r', linestyle='--', label='Block 1/2 分界')
plt.xlabel('窗口起始试次')
plt.ylabel('转移概率')
plt.title('从Block1到Block2的转移概率趋势')
plt.legend()
plt.grid(True)
plt.show()

内容的提问来源于stack exchange,提问作者Kshtj

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 17:43:17