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

如何模拟已知行边际的列联表?列分布匹配总计且时间列无邻域相关性

满足需求的列联表模拟抽样方法

针对你需要模拟已知行边际、列分布接近总计列且相邻时间列相关性弱的列联表,这里提供两种可行的抽样方案:

方案1:分层独立抽样+行边际校准

这是最直接的方案,核心是让每一列独立按照总计列的比例抽样,再校准行边际确保符合要求,天然保证列间相关性低。

实现步骤

  1. 提取总计列的比例作为每列抽样的基准
  2. 对每个时间列(X1-X5),用多项分布独立生成初始数值
  3. 微调初始数值,让每行的总和严格匹配给定的行边际(A=80、B=100、C=120、D=40)

完整代码实现

import pandas as pd
import numpy as np

def cal_perc(x, total):
    return round((x / total) * 100, 2)

# 初始化原始框架
df = pd.DataFrame({'X1':[None,None,None,None,None],
              'X2':[None,None,None,None,None],
              'X3':[None,None,None,None,None],
              'X4':[None,None,None,None,None],
              'X5':[None,None,None,None,None],
              'total':[80,100,120,40,340]})

df.index = ["A","B","C","D","total"]
df["%"] = [cal_perc(x, 340) for x in df["total"]]

# 获取行边际目标值和基准比例
row_targets = df.loc[["A","B","C","D"], "total"].values
base_proportions = df.loc[["A","B","C","D"], "%"].values / 100
col_count = 5
col_total = 340  # 每列总和与总计一致,可按需调整

# 独立生成每列的初始抽样值
sampled_cols = []
for _ in range(col_count):
    # 多项分布按基准比例生成列数据
    initial_vals = np.random.multinomial(col_total, base_proportions)
    sampled_cols.append(initial_vals)

# 转换为数据框
result_df = pd.DataFrame(sampled_cols).T
result_df.columns = [f"X{i+1}" for i in range(col_count)]
result_df.index = ["A","B","C","D"]

# 校准行边际:调整每行总和到目标值
for row_idx, target in enumerate(row_targets):
    current_sum = result_df.iloc[row_idx].sum()
    diff = target - current_sum
    if diff != 0:
        # 随机选择列分配差值,避免引入系统性偏差
        adjust_cols = np.random.choice(result_df.columns, abs(diff), replace=True)
        for col in adjust_cols:
            result_df.loc[result_df.index[row_idx], col] += 1 if diff > 0 else -1

# 添加总计行和百分比列
result_df.loc["total"] = result_df.sum(axis=0)
result_df["total"] = result_df.sum(axis=1)
result_df["%"] = [cal_perc(x, 340) for x in result_df["total"]]

print(result_df)

方案优势

  • 每列独立抽样,相邻时间列的相关性天然极低
  • 校准步骤确保行边际完全符合要求
  • 列分布与总计列的基准比例高度接近

方案2:Dirichlet分布抽样+双边际校准

如果需要更灵活的比例波动控制,可以用Dirichlet分布生成每行的列比例,再缩放至行边际,同时微调列分布使其接近总计比例。

核心逻辑

  1. 对每行,基于基准比例设置Dirichlet分布的参数(加入小噪声项增强独立性)
  2. 用生成的比例乘以该行的边际总和,得到初始单元格值
  3. 同时校准行、列边际,确保行总和符合要求且列分布接近基准

简化代码示例

# 接上面的初始化代码
alpha = base_proportions * 100  # 控制分布集中度,值越大越接近基准比例
sampled_data = []
for target in row_targets:
    # 生成该行的列比例
    row_probs = np.random.dirichlet(alpha)
    # 缩放至行目标值并取整
    row_vals = np.round(row_probs * target).astype(int)
    sampled_data.append(row_vals)

result_df = pd.DataFrame(sampled_data, index=["A","B","C","D"], columns=[f"X{i+1}" for i in range(col_count)])
# 校准列分布(可选,若列偏差过大时调整)
# ...(此处可加入列比例校准逻辑)

注意事项

  • 若要严格控制列分布与总计列的相似度,可在抽样后计算列比例,若偏差超过阈值则重新抽样
  • 降低列间相关性的关键是避免基于前一列的数值生成后续列,保持每列的独立性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 08:36:14