控制Kruskal-Wallis H检验模拟数据的样本量,核心是调整分组数据的长度参数,同时保证组间样本量的可配置性(均衡/不均衡均可)。以下是具体方法、代码示例和实操技巧,结合之前的场景逐一拆解:
一、核心控制逻辑:样本量的3种设置方式
模拟数据的样本量完全由分组数据的元素个数决定,主要有3种实现思路,适用于不同需求:
| 控制方式 | 适用场景 | 核心代码逻辑 |
|---|---|---|
| 直接指定每组长度 | 样本量固定(如A组50,B组60) | ['A']*50 + ['B']*60 |
| 变量参数化 | 需灵活调整样本量 | n1=50; ['A']*n1 |
| 比例分配 | 按比例拆分总样本量 | total=200; n1=int(total*0.3) |
二、分场景实操代码(附带样本量控制)
1. 基础场景:固定每组样本量(均衡/不均衡均可)
需求:设置 CHB 组 50 例、NAFLD 组 50 例、合并组 100 例,总样本量 200。
import pandas as pd
import numpy as np
# 1. 定义每组样本量(参数化,方便修改)
n_chb = 50
n_nafld = 50
n_combined = 100
# 2. 生成分组列:通过列表乘法控制样本量
groups = ['CHB'] * n_chb + ['NAFLD'] * n_nafld + ['CHB+NAFLD'] * n_combined
# 3. 生成对应长度的因变量数据
alp_data = np.concatenate([
np.random.lognormal(4.3, 0.5, n_chb), # 长度匹配 n_chb
np.random.lognormal(4.5, 0.6, n_nafld), # 长度匹配 n_nafld
np.random.lognormal(4.4, 0.55, n_combined) # 长度匹配 n_combined
])
# 4. 构建DataFrame
data = pd.DataFrame({
'group': groups,
'ALP': alp_data
})
# 验证样本量
print("各组样本量:")
print(data['group'].value_counts())
print(f"总样本量:{len(data)}")
关键点:列表乘法 ['组名']*样本量 是最直接的方式,因变量数组长度必须和分组列长度完全一致,否则会报错。
2. 进阶场景:按比例分配总样本量
需求:总样本量 300,对照组占 20%、调查诱导组 25%、脚本机器人组 25%、生成式机器人组 30%。
# 1. 定义总样本量和比例
total_n = 300
props = [0.2, 0.25, 0.25, 0.3] # 四组比例
groups_name = ['对照组', '调查诱导组', '脚本机器人组', '生成式机器人组']
# 2. 计算每组样本量(四舍五入取整)
n_list = [int(total_n * p) for p in props]
# 修正:避免四舍五入后总样本量不一致
n_list[-1] = total_n - sum(n_list[:-1])
# 3. 生成分组列和因变量
groups = []
score_data = []
for i, name in enumerate(groups_name):
groups += [name] * n_list[i]
# 按组生成评分数据
mu = 3 + i * 0.8 # 组间mu递增,制造差异
scores = np.random.poisson(mu, n_list[i]) + np.random.normal(0, 0.5, n_list[i])
score_data.extend(scores)
# 4. 构建DataFrame
data = pd.DataFrame({
'group': groups,
'confidence_score': score_data
})
# 验证
print("各组样本量(按比例分配):")
print(data['group'].value_counts())
print(f"总样本量:{len(data)}")
关键点:按比例分配后,最后一组样本量用 总样本量 - 其他组之和 修正,避免因四舍五入导致总样本量偏差。
3. 实用场景:批量生成多指标数据(统一样本量)
需求:3 个污染等级,每组样本量 40,共 120 样本,包含 3 个生物多样性指标。
# 1. 统一设置每组样本量
n_per_group = 40
groups = ['轻度污染', '中度污染', '重度污染']
n_groups = len(groups)
# 2. 生成分组列
groups_col = []
for g in groups:
groups_col += [g] * n_per_group
# 3. 生成多指标数据(每组长度都是n_per_group)
alpha = np.concatenate([np.random.normal(6+i*(-1.5), 0.8, n_per_group) for i in range(n_groups)])
beta = np.concatenate([np.random.normal(3.5+i*(-1), 0.6, n_per_group) for i in range(n_groups)])
species = np.concatenate([np.random.poisson(45-i*10, n_per_group) for i in range(n_groups)])
# 4. 构建DataFrame
data = pd.DataFrame({
'pollution_level': groups_col,
'alpha_diversity': alpha,
'beta_diversity': beta,
'species_richness': species
})
# 验证
print("各组样本量(多指标):")
print(data['pollution_level'].value_counts())
关键点:多指标场景下,所有因变量的长度必须和分组列一致,用列表推导式+np.concatenate 可高效生成。
三、实操注意事项
- 长度一致性:分组列的长度 ≡ 每个因变量数组的长度,这是构建DataFrame的硬性要求,否则会触发
ValueError: arrays must all be same length。 - 随机种子固定:若需结果可复现,在生成数据前添加
np.random.seed(42),样本量不影响随机性,只影响数据量大小。 - 样本量合理性:
- 每组样本量不宜过小(建议≥20),否则K-W检验的检验效能(power)会下降,难以检测到真实差异;
- 不等样本量完全不影响K-W检验的执行,该检验对样本量不均衡的鲁棒性很强。
四、拓展:动态调整样本量的函数封装
如果需要反复调整样本量,可封装成函数,一键生成数据:
def generate_kw_data(n_per_group_list, group_names, dist_type='lognormal', dist_params=None):
"""
生成K-W检验模拟数据
:param n_per_group_list: 每组样本量列表,如[50,60,100]
:param group_names: 组名列表,如['A','B','C']
:param dist_type: 分布类型,lognormal/poisson/normal
:param dist_params: 每组分布参数列表,如[(4.3,0.5), (4.5,0.6)]
:return: DataFrame
"""
groups = []
values = []
for i, n in enumerate(n_per_group_list):
groups += [group_names[i]] * n
params = dist_params[i]
if dist_type == 'lognormal':
val = np.random.lognormal(params[0], params[1], n)
elif dist_type == 'poisson':
val = np.random.poisson(params[0], n)
elif dist_type == 'normal':
val = np.random.normal(params[0], params[1], n)
values.extend(val)
return pd.DataFrame({'group': groups, 'value': values})
# 调用函数:生成3组数据,样本量[40,50,60]
data = generate_kw_data(
n_per_group_list=[40,50,60],
group_names=['HIIT', '持续有氧', '不运动'],
dist_type='lognormal',
dist_params=[(3.2,0.4), (3.5,0.5), (3.8,0.6)]
)
print(data['group'].value_counts())