引言:认知融合问卷分析的重要性

认知融合(Cognitive Fusion)是接纳与承诺疗法(ACT)中的核心概念,指个体将思想与现实混淆,过度认同内在体验的心理过程。认知融合问卷(如CFQ, Cognitive Fusion Questionnaire)是测量这一构念的常用工具。在心理学研究和临床实践中,对这类问卷进行科学分析至关重要,它直接影响研究结论的可靠性和干预效果的评估。本指南将从理论基础出发,系统阐述从数据清洗到高级统计建模的全流程分析方法,帮助研究者掌握严谨的分析技术。

第一部分:认知融合的理论基础与问卷设计

认知融合的概念框架

认知融合的概念源于关系框架理论(RFT),它描述了人类语言和认知的”衍生关系”特性如何导致心理困扰。当个体将语言等同于现实时,就会产生认知融合,例如将”我感到焦虑”等同于”我是一个焦虑的人”。理解这一理论背景对问卷分析至关重要,因为它决定了问卷应测量的核心维度和潜在的心理结构。

常用认知融合问卷介绍

目前最常用的是Gil-lucas等人开发的CFQ(Cognitive Fusion Questionnaire),包含7个条目,采用7点计分(1=非常不符合,7=非常符合)。例如条目1:”我的想法会让我感到情绪困扰”。其他变体包括简版CFQ-7和针对特定人群的改编版本。了解问卷的结构和计分方式是分析的前提。

1.1 问卷设计的理论依据

认知融合问卷的设计严格遵循ACT理论模型。每个条目都针对特定的认知融合表现:

  • 思维内容融合(如”我必须控制我的想法”)
  • 思维过程融合(如”如果我有负面想法,就意味着我是坏人”)
  • 思维-情绪融合(如”我的想法让我感到痛苦”)

这种理论驱动的设计确保了问卷的内容效度,也为后续的因子分析提供了理论预期。

第二部分:数据清洗与预处理

数据收集与导入

在分析之前,首先需要规范地收集数据。假设我们使用Qualtrics或问卷星等平台收集了500份CFQ问卷数据,导出为CSV格式。使用Python的pandas库进行初步导入:

import pandas as pd
import numpy as np

# 导入数据
df = pd.read_csv('cognitive_fusion_data.csv')

# 查看数据基本信息
print(df.info())
print(df.head())

# 检查数据维度
print(f"数据集包含 {df.shape[0]} 个样本,{df.shape[1]} 个变量")

缺失值处理

缺失值是问卷数据常见问题。需要系统评估缺失模式:

# 计算每个变量的缺失比例
missing_ratio = df.isnull().mean() * 100
print("各变量缺失比例:")
print(missing_ratio)

# 可视化缺失模式
import missingno as msno
msno.matrix(df)

# 根据缺失机制选择处理方法
# 如果是完全随机缺失(MCAR),可以使用删除或均值插补
# 如果是随机缺失(MAR),建议使用多重插补

# 简单删除法(适用于缺失<5%)
df_clean = df.dropna()

# 均值插补(适用于小样本)
df_imputed = df.fillna(df.mean())

# 多重插补(推荐方法)
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

imputer = IterativeImputer(random_state=0)
df_imputed = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

异常值检测与处理

异常值可能影响统计结果,需要系统检测:

# 方法1:箱线图法检测异常值
import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(12, 6))
sns.boxplot(data=df_imputed)
plt.title('CFQ各条目得分箱线图')
plt.show()

# 方法2:Z分数法(适用于正态分布)
from scipy import stats
z_scores = np.abs(stats.zscore(df_imputed))
outliers = (z_scores > 3).any(axis=1)
print(f"检测到 {outliers.sum()} 个异常值样本")

# 方法3:孤立森林算法(适用于多维数据)
from sklearn.ensemble import IsolationForest
iso_forest = IsolationForest(contamination=0.05, random_state=42)
outlier_labels = iso_forest.fit_predict(df_imputed)
outlier_indices = np.where(outlier_labels == -1)[0]
print(f"孤立森林检测到 {len(outlier_indices)} 个异常值")

# 处理策略:根据理论判断是否删除或Winsorize
# Winsorize处理(将极端值替换为第5/95百分位数)
from scipy.stats.mstats import winsorize
df_winsorized = df_imputed.apply(lambda x: winsorize(x, limits=[0.05, 0.05]))

数据分布检验

检查数据是否符合参数检验的假设:

# 正态性检验(Shapiro-Wilk检验)
for col in df_winsorized.columns:
    stat, p = stats.shapiro(df_winsorized[col])
    print(f"{col}: W={stat:.3f}, p={p:.4f}")
    if p < 0.05:
        print(f"  → 拒绝正态性假设")
    else:
        print(f"  → 接受正态性假设")

# 可视化分布
plt.figure(figsize=(12, 8))
for i, col in enumerate(df_winsorized.columns, 1):
    plt.subplot(2, 4, i)
    sns.histplot(df_winsorized[col], kde=True)
    plt.title(col)
plt.tight_layout()
plt.show()

数据标准化与反向计分

检查问卷是否有反向计分条目并进行转换:

# 假设CFQ的第2、4、6条目是反向计分(实际需根据问卷说明)
reverse_items = ['CFQ2', 'CFQ4', 'CFQ6']

for item in reverse_items:
    if item in df_winsorized.columns:
        # 反向计分:7点计分转换为1-7的反向
        df_winsorized[item] = 8 - df_winsorized[item]
        print(f"已反向计分:{item}")

# 计算总分(如果需要)
df_winsorized['CFQ_Total'] = df_winsorized.sum(axis=1)
print("CFQ总分描述统计:")
print(df_winsorized['CFQ_Total'].describe())

第三部分:信度分析

3.1 内部一致性信度

内部一致性反映问卷各条目测量同一构念的程度:

import pingouin as pg

# 计算Cronbach's Alpha
alpha_result = pg.cronbach_alpha(data=df_winsorized.iloc[:, :7])
print(f"Cronbach's Alpha系数: {alpha_result[0]:.3f}")
print(f"95%置信区间: ({alpha_result[1][0]:.3f}, {alpha_result[1][1]:.3f})")

# 逐项删除后的Alpha值
for item in df_winsorized.columns[:7]:
    alpha_if_deleted = pg.cronbach_alpha(data=df_winsorized.drop(columns=[item]))
    print(f"删除 {item} 后的Alpha: {alpha_if_deleted[0]:.3f}")

# 分半信度(如果问卷条目较多)
# 将条目分为奇偶两部分
odd_items = df_winsorized.columns[0::2]  # 奇数索引
even_items = df_w1
even_items = df_winsorized.columns[1::2]  # 偶数索引

odd_sum = df_winsorized[odd_items].sum(axis=1)
even_sum = df_winsorized[even_items].sum(axis=1)

# Spearman-Brown校正
split_half = pg.corr(odd_sum, even_sum)
r = split_half['r'].values[0]
spearman_brown = (2 * r) / (1 + r)
print(f"分半信度系数(Spearman-Brown校正): {spearman_brown:.3f}")

3.2 重测信度

如果有纵向数据,可以计算重测信度:

# 假设有时间1和时间2的数据
# df_long = pd.read_csv('longitudinal_data.csv')

# 计算皮尔逊相关系数
# retest_corr = pg.corr(df_long['CFQ_T1'], df_long['CFQ_T2'])
# print(f"重测信度: {retest_corr['r'].values[0]:.3f}")

# 如果数据是配对样本,可以使用ICC
# from sklearn.metrics import cohen_kappa_score
# 或使用pingouin的ICC函数
# icc = pg.intraclass_corr(data=df_long, targets='subject', raters='time', ratings='CFQ_score')

3.3 信度结果解读标准

  • Cronbach’s Alpha:>0.7 可接受,>0.8 良好,>0.9 优秀
  • 分半信度:>0.7 可接受
  • 重测信度:>0.7 表明时间稳定性良好

如果信度不达标,需要检查:

  1. 条目是否测量同一构念
  2. 是否存在反向计分错误
  3. 样本量是否足够
  4. 被试是否理解条目含义

第四部分:效度分析

4.1 结构效度:探索性因子分析(EFA)

EFA用于探索问卷的潜在结构:

from factor_analyzer import FactorAnalyzer
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
from factor_analyzer.factor_analyzer import calculate_kmo

# 1. 适用性检验
# Bartlett球形检验
chi_square_value, p_value = calculate_bartlett_sphericity(df_winsorized.iloc[:, :7])
print(f"Bartlett球形检验: χ² = {chi_square_value:.2f}, p = {p_value:.4f}")

# KMO检验
kmo_all, kmo_model = calculate_kmo(df_winsorized.iloc[:, :7])
print(f"KMO值: {kmo_model:.3f}")
print("KMO标准: >0.6 可接受,>0.8 良好")

# 2. 因子提取
fa = FactorAnalyzer(n_factors=1, rotation=None)  # 理论预期是单因子结构
fa.fit(df_winsorized.iloc[:, :7])

# 查看因子载荷
loadings = fa.loadings_
print("因子载荷矩阵:")
for i, item in enumerate(df_winsorized.columns[:7]):
    print(f"{item}: {loadings[i, 0]:.3f}")

# 查看公因子方差
communalities = fa.get_communalities()
print("\n公因子方差:")
for i, item in enumerate(df_winsorized.columns[:7]):
    print(f"{item}: {communalities[i]:.3f}")

# 3. 碎石图确定因子数量
fa = FactorAnalyzer(n_factors=7, rotation=None)
fa.fit(df_winsorized.iloc[:, :7])
ev, v = fa.get_eigenvalues()

plt.figure(figsize=(8, 6))
plt.plot(range(1, 8), ev, 'o-')
plt.axhline(y=1, color='r', linestyle='--')
plt.title('碎石图')
plt.xlabel('因子数量')
plt.ylabel('特征值')
plt.show()

# 4. 验证性因子分析(CFA)
import semopy as sem

# 定义模型(单因子模型)
model_spec = """
# 测量模型
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
"""

# 拟合模型
mod = sem.Model(model_spec)
mod.fit(df_winsorized.iloc[:, :7])
print(mod.summary())

# 模型拟合指标
# CFI > 0.9, TLI > 0.9, RMSEA < 0.08, SRMR < 0.08

4.2 效标效度

评估问卷与其他变量的关系:

# 假设我们有焦虑量表(Anxiety)、抑郁量表(Depression)和生活满意度(LifeSat)
# 计算相关矩阵
criteria_vars = ['Anxiety', 'Depression', 'LifeSat']
cfq_vars = df_winsorized.columns[:7]

# 合并数据(假设df_full包含所有变量)
# 相关分析
corr_matrix = df_full[cfq_vars + criteria_vars].corr()
print("CFQ与效标变量的相关矩阵:")
print(corr_matrix.loc[criteria_vars, cfq_vars])

# 绘制热图
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('CFQ与效标变量相关矩阵')
plt.show()

# 差异检验:高分组 vs 低分组
# 创建高分组(前27%)和低分组(后27%)
cfq_total = df_full[cfq_vars].sum(axis=1)
high_group = df_full[cfq_total > np.percentile(cfq_total, 73)]
low_group = df_full[cfq_total < np.percentile(cfq_total, 27)]

# 比较两组在效标变量上的差异
from scipy.stats import ttest_ind
for var in criteria_vars:
    t_stat, p_val = ttest_ind(high_group[var], low_group[var])
    print(f"{var}: t = {t_stat:.3f}, p = {p_val:.4f}")

4.3 聚合效度与区分效度

# 聚合效度:CFQ与ACT其他核心过程的关系
# 假设我们有接纳量表(AAQ)、正念(FFMQ)等
act_vars = ['AAQ', 'FFMQ', 'Values']
corr_matrix_act = df_full[cfq_vars + act_vars].corr()
print("CFQ与ACT核心过程的相关:")
print(corr_matrix_act.loc[act_vars, cfq_vars])

# 区分效度:CFQ与其他无关构念的关系
# 假设有社会赞许性量表(Marlowe-Crowne)
irrelevant_vars = ['Social_Desirability']
corr_irrelevant = df_full[cfq_vars + irrelevant_vars].corr()
print("\nCFQ与无关构念的相关(应接近0):")
print(corr_irrelevant.loc[irrelevant_vars, cfq_vars])

第五部分:统计建模技巧

5.1 描述性统计与可视化

# 完整描述性统计
desc_stats = df_winsorized.describe()
print(desc_stats)

# 绘制得分分布
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
sns.histplot(df_winsorized['CFQ_Total'], kde=True, bins=20)
plt.title('CFQ总分分布')
plt.xlabel('总分')
plt.ylabel('频数')

plt.subplot(1, 2, 2)
sns.boxplot(y=df_winsorized['CFQ_Total'])
plt.title('CFQ总分箱线图')
plt.ylabel('总分')

plt.tight_layout()
plt.show()

# 条目得分分布
plt.figure(figsize=(15, 10))
for i, col in enumerate(df_winsorized.columns[:7], 1):
    plt.subplot(2, 4, i)
    sns.countplot(x=df_winsorized[col])
    plt.title(f'条目 {col}')
    plt.xlabel('得分')
    plt.ylabel('频数')
plt.tight_layout()
plt.show()

5.2 组间差异分析

# 独立样本t检验(性别差异)
if 'Gender' in df_full.columns:
    male = df_full[df_full['Gender'] == 'Male']['CFQ_Total']
    female = df_full[df_full['Gender'] == 'Female']['CFQ_Total']
    
    t_stat, p_val = stats.ttest_ind(male, female)
    print(f"性别差异: t({len(male)+len(female)-2}) = {t_stat:.3f}, p = {p_val:.4f}")
    
    # 效应量Cohen's d
    pooled_std = np.sqrt(((len(male)-1)*male.var() + (len(female)-1)*female.var()) / 
                        (len(male)+len(female)-2))
    d = (male.mean() - female.mean()) / pooled_std
    print(f"效应量 d = {d:.3f}")

# 单因素方差分析(年龄组)
if 'Age_Group' in df_full.columns:
    groups = [group['CFQ_Total'].values for name, group in df_full.groupby('Age_Group')]
    f_stat, p_val = stats.f_oneway(*groups)
    print(f"年龄组差异: F = {f_stat:.3f}, p = {p_val:.4f}")
    
    # 事后检验(Tukey HSD)
    from statsmodels.stats.multicomp import pairwise_tukeyhsd
    tukey = pairwise_tukeyhsd(df_full['CFQ_Total'], df_full['Age_Group'])
    print(tukey)

5.3 回归分析预测模型

# 线性回归:预测CFQ得分
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 准备特征矩阵(假设包含人口学变量和预测变量)
features = ['Age', 'Education', 'Anxiety', 'Depression', 'Values']
X = df_full[features]
y = df_full['CFQ_Total']

# 处理分类变量(如有)
X = pd.get_dummies(X, drop_first=True)

# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 拟合模型
lr = LinearRegression()
lr.fit(X_train, y_train)

# 预测与评估
y_pred = lr.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"回归模型性能:")
print(f"均方误差 (MSE): {mse:.3f}")
print(f"R²: {r2:.3f}")

# 查看系数
coef_df = pd.DataFrame({
    '变量': X.columns,
    '系数': lr.coef_,
    '绝对值': np.abs(lr.coef_)
}).sort_values('绝对值', ascending=False)
print("\n回归系数(按重要性排序):")
print(coef_df)

# 使用statsmodels获取详细统计信息
import statsmodels.api as sm
X_sm = sm.add_constant(X_train)
model_sm = sm.OLS(y_train, X_sm).fit()
print(model_sm.summary())

5.4 中介与调节效应分析

# 中介模型:认知融合在ACT核心过程与心理健康间的中介作用
# 使用semopy进行结构方程建模

model_mediation = """
# 测量模型
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
Anxiety =~ Anxiety1 + Anxiety2 + Anxiety3
Depression =~ Depression1 + Depression2 + Depression3
Acceptance =~ AAQ1 + AAQ2 + AAQ3

# 结构模型
CFQ ~ Acceptance
Anxiety ~ CFQ + Acceptance
Depression ~ CFQ + Acceptance

# 间接效应
Acceptance_CFQ_Anx := Acceptance -> CFQ -> Anxiety
Acceptance_CFQ_Dep := Acceptance -> CFQ -> Depression
"""

mod_med = sem.Model(model_mediation)
mod_med.fit(df_full)
print(mod_med.summary())

# Bootstrap检验间接效应
# semopy支持bootstrap,但需要额外配置
# 替代方案:使用process宏或手动bootstrap

# 调节效应:性别调节CFQ与抑郁的关系
model_moderation = """
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
Depression =~ Depression1 + Depression2 + Depression3
Gender =~ 1*Gender_Male  # 二分变量

# 交互项(需要预先创建)
CFQ_Gender ~ CFQ * Gender
Depression ~ CFQ + Gender + CFQ_Gender
"""

5.5 潜在类别分析(LCA)

识别认知融合的亚群体:

from sklearn.mixture import GaussianMixture
from sklearn.preprocessing import StandardScaler

# 使用CFQ条目进行潜在类别分析
cfq_items = df_winsorized.columns[:7]
X_lca = df_winsorized[cfq_items]

# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_lca)

# 尝试不同类别数
bic_scores = []
aic_scores = []
for n in range(2, 6):
    gmm = GaussianMixture(n_components=n, random_state=42)
    gmm.fit(X_scaled)
    bic_scores.append(gmm.bic(X_scaled))
    aic_scores.append(gmm.aic(X_scaled))

# 绘制信息准则
plt.figure(figsize=(8, 5))
plt.plot(range(2, 6), bic_scores, 'o-', label='BIC')
plt.plot(range(2, 6), aic_scores, 'o-', label='AIC')
plt.xlabel('类别数')
plt.ylabel('信息准则')
plt.title('潜在类别分析:选择最优类别数')
plt.legend()
plt.show()

# 拟合最优模型(假设3类最优)
optimal_n = 3
gmm_optimal = GaussianMixture(n_components=optimal_n, random_state=42)
gmm_optimal.fit(X_scaled)
class_labels = gmm_optimal.predict(X_scaled)

# 分析各类别特征
df_lca = df_winsorized.copy()
df_lca['Class'] = class_labels

print("各类别样本量:")
print(df_lca['Class'].value_counts())

print("\n各类别CFQ总分均值:")
print(df_lca.groupby('Class')['CFQ_Total'].mean())

print("\n各类别在各条目上的特征:")
print(df_lca.groupby('Class')[cfq_items].mean())

5.6 纵向数据分析(如果有重复测量)

# 重复测量ANOVA或混合效应模型
# 假设数据格式:每个被试有时间1、时间2、时间3的CFQ得分

# 使用混合效应模型(推荐)
import statsmodels.formula.api as smf

# 准备长格式数据
# df_long = pd.melt(df_wide, id_vars=['SubjectID'], value_vars=['CFQ_T1', 'CFQ_T2', 'CFQ_T3'],
#                   var_name='Time', value_name='CFQ')

# 混合效应模型
# model = smf.mixedlm("CFQ ~ Time + Group", df_long, groups=df_long["SubjectID"])
# result = model.fit()
# print(result.summary())

# 如果是干预研究,可以比较组间变化
# model = smf.mixedlm("CFQ ~ Time * Group", df_long, groups=df_long["SubjectID"])

第六部分:高级分析技巧与注意事项

6.1 处理非正态分布数据

# 如果数据严重偏态,考虑非参数方法
# Mann-Whitney U检验(替代t检验)
from scipy.stats import mannwhitneyu

# 假设比较高低分组
high_scores = df_full.loc[df_full['CFQ_Total'] > df_full['CFQ_Total'].median(), 'CFQ_Total']
low_scores = df_full.loc[df_full['CFQ_Total'] <= df_full['CRQ_Total'].median(), 'CFQ_Total']

u_stat, p_val = mannwhitneyu(high_scores, low_scores)
print(f"Mann-Whitney U检验: U = {u_stat}, p = {p_val:.4f}")

# Spearman相关(替代Pearson相关)
corr_spearman = df_full[cfq_vars + criteria_vars].corr(method='spearman')
print("Spearman相关矩阵:")
print(corr_s1

6.2 共同方法偏差检验

# Harman单因子检验
from factor_analyzer import FactorAnalyzer

# 将所有变量(包括CFQ和效标)放入EFA
all_vars = cfq_vars + criteria_vars
fa_harman = FactorAnalyzer(n_factors=1, rotation=None)
fa_harman.fit(df_full[all_vars])

# 查看第一个因子解释的方差比例
ev, _ = fa_harman.get_eigenvalues()
first_factor_variance = ev[0] / sum(ev)
print(f"第一个因子解释的方差比例: {first_factor_variance:.3f}")

# 如果>40%,可能存在共同方法偏差
if first_factor_variance > 0.4:
    print("警告:可能存在共同方法偏差")
else:
    print("共同方法偏差在可接受范围内")

# 更严格的方法:控制未测量的潜在方法因子(ULMC)
# 需要使用CFA,比较包含和不包含方法因子的模型

6.3 多组比较(测量不变性)

# 检验问卷在不同群体(如性别、文化)中的测量不变性
# 需要使用CFA多组分析

# 1. 形态不变性(Configural Invariance)
# 2. 弱不变性(Metric Invariance)
# 3. 强不变性(Scalar Invariance)
# 4. 严格不变性(Strict Invariance)

# 使用semopy的多组分析功能
# model = """
# CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
# """

# 分组拟合
# groups = ['Male', 'Female']
# for group in groups:
#     group_data = df_full[df_full['Gender'] == group]
#     mod = sem.Model(model)
#     mod.fit(group_data)

# 比较模型差异(ΔCFI < 0.01 表示不变性成立)

6.4 敏感性分析

# 检验分析结果的稳健性
# 1. 使用不同缺失值处理方法比较结果
methods = ['complete', 'mean', 'median', 'knn']
results = {}

for method in methods:
    if method == 'complete':
        df_method = df.dropna()
    elif method == 'mean':
        df_method = df.fillna(df.mean())
    elif method == 'median':
        df_method = df.fillna(df.median())
    elif method == 'knn':
        from sklearn.impute import KNNImputer
        imputer = KNNImputer(n_neighbors=5)
        df_method = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
    
    # 计算Alpha
    alpha = pg.cronbach_alpha(data=df_method.iloc[:, :7])[0]
    results[method] = alpha

print("不同缺失值处理方法的Alpha系数:")
for method, alpha in results.items():
    print(f"{method}: {alpha:.3f}")

# 2. 使用不同异常值处理阈值
thresholds = [2.5, 3.0, 3.5]
for thresh in thresholds:
    z_scores = np.abs(stats.zscore(df_imputed))
    outliers = (z_scores > thresh).any(axis=1)
    df_no_outliers = df_imputed[~outliers]
    alpha = pg.cronbach_alpha(data=df_no_outliers.iloc[:, :7])[0]
    print(f"Z阈值={thresh}时的Alpha: {alpha:.3f}")

第七部分:结果报告与解释

7.1 报告标准

根据APA和期刊要求,信效度报告应包括:

  • 信度:Cronbach’s Alpha值、置信区间、条目-总分相关
  • 效度:因子载荷、模型拟合指数(CFI, TLI, RMSEA, SRMR)
  • 效标关联效度:与相关变量的相关系数
  • 测量不变性:多组比较结果

7.2 结果解释示例

# 生成报告摘要
def generate_report(df, cfq_vars):
    report = {}
    
    # 信度
    alpha = pg.cronbach_alpha(data=df[cfq_vars])[0]
    report['Cronbach_alpha'] = alpha
    
    # 描述统计
    report['Mean'] = df[cfq_vars].mean().mean()
    report['SD'] = df[cfq_vars].std().mean()
    
    # 效度(假设已进行CFA)
    # report['CFI'] = 0.95
    # report['RMSEA'] = 0.04
    
    return report

report = generate_report(df_winsorized, cfq_vars)
print("分析结果摘要:")
for key, value in report.items():
    print(f"{key}: {value:.3f}")

7.3 可视化结果

# 创建发表质量的图表
plt.style.use('seaborn-v0_8-whitegrid')
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 1. 条目载荷图
loadings = fa.loadings_
axes[0, 0].bar(range(len(loadings)), loadings[:, 0])
axes[0, 0].set_title('因子载荷')
axes[0, 0].set_ylabel('载荷值')
axes[0, 0].set_xticks(range(len(loadings)))
axes[0, 0].set_xticklabels(cfq_vars, rotation=45)

# 2. 效标相关热图
corr_matrix = df_full[cfq_vars + criteria_vars].corr()
sns.heatmap(corr_matrix.loc[criteria_vars, cfq_vars], annot=True, cmap='coolwarm', 
            center=0, ax=axes[0, 1])
axes[0, 1].set_title('效标相关')

# 3. 组间差异
if 'Gender' in df_full.columns:
    sns.boxplot(data=df_full, x='Gender', y='CFQ_Total', ax=axes[1, 0])
    axes[1, 0].set_title('性别差异')

# 4. 回归系数
coef_df = pd.DataFrame({'变量': X.columns, '系数': lr.coef_})
sns.barplot(data=coef_df, x='系数', y='变量', ax=axes[1, 1])
axes[1, 1].set_title('回归系数')

plt.tight_layout()
plt.savefig('cognitive_fusion_analysis.png', dpi=300, bbox_inches='tight')
plt.show()

第八部分:常见问题与解决方案

8.1 信度不达标

问题:Alpha < 0.7

解决方案

  1. 检查反向计分是否正确
  2. 删除低相关条目(item-total correlation < 0.3)
  3. 增加样本量
  4. 考虑问卷是否适合当前人群
# 识别低相关条目
item_total_corr = []
for item in cfq_vars:
    corr = pg.corr(df_winsorized[item], df_winsorized['CFQ_Total'])
    item_total_corr.append(corr['r'].values[0])

low_corr_items = [item for i, item in enumerate(cfq_vars) if item_total_corr[i] < 0.3]
print("低相关条目(r < 0.3):", low_corr_items)

8.2 CFA模型拟合不佳

问题:CFI < 0.9 或 RMSEA > 0.08

解决方案

  1. 检查因子载荷是否<0.4
  2. 考虑添加残差相关
  3. 检查数据是否有多维结构
  4. 考虑使用修正指数(Modification Indices)
# 识别低载荷条目
low_loadings = [item for i, item in enumerate(cfq_vars) if abs(loadings[i, 0]) < 0.4]
print("低载荷条目(<0.4):", low_loadings)

8.3 样本量不足

问题:样本量 < 100

解决方案

  1. 使用Bootstrap重抽样
  2. 采用贝叶斯方法
  3. 报告置信区间而非仅p值
  4. 考虑使用简版问卷

8.4 数据非正态

问题:Shapiro-Wilk检验p < 0.05

解决方案

  1. 使用非参数检验
  2. 数据转换(如对数、平方根)
  3. 使用稳健标准误
  4. 增加样本量(中心极限定理)

第九部分:完整分析流程示例

从原始数据到最终报告

# 完整流程封装
def analyze_cognitive_fusion_questionnaire(df, cfq_items, demographics=None):
    """
    完整分析CFQ问卷的函数
    
    参数:
    df: 原始数据DataFrame
    cfq_items: CFQ条目名称列表
    demographics: 人口学变量列表
    """
    
    print("="*60)
    print("认知融合问卷完整分析流程")
    print("="*60)
    
    # 1. 数据清洗
    print("\n1. 数据清洗...")
    # 缺失值处理
    missing_rate = df[cfq_items].isnull().mean().mean()
    print(f"  平均缺失率: {missing_rate:.2%}")
    
    if missing_rate > 0.05:
        print("  → 使用多重插补")
        from sklearn.experimental import enable_iterative_imputer
        from sklearn.impute import IterativeImputer
        imputer = IterativeImputer(random_state=0)
        df_imputed = pd.DataFrame(imputer.fit_transform(df[cfq_items]), columns=cfq_items)
    else:
        df_imputed = df[cfq_items].dropna()
    
    # 异常值检测
    z_scores = np.abs(stats.zscore(df_imputed))
    outliers = (z_scores > 3).any(axis=1)
    print(f"  异常值样本: {outliers.sum()} 个")
    df_clean = df_imputed[~outliers]
    
    # 2. 信度分析
    print("\n2. 信度分析...")
    alpha = pg.cronbach_alpha(data=df_clean)[0]
    print(f"  Cronbach's Alpha: {alpha:.3f}")
    
    if alpha < 0.7:
        print("  → 信度不达标,检查数据质量")
    else:
        print("  → 信度良好")
    
    # 3. 效度分析(EFA)
    print("\n3. 效度分析(探索性因子分析)...")
    from factor_analyzer import FactorAnalyzer
    fa = FactorAnalyzer(n_factors=1, rotation=None)
    fa.fit(df_clean)
    loadings = fa.loadings_
    
    print("  因子载荷:")
    for i, item in enumerate(cfq_items):
        print(f"    {item}: {loadings[i,0]:.3f}")
    
    # 4. 描述性统计
    print("\n4. 描述性统计...")
    desc = df_clean.describe()
    print(f"  总分均值: {df_clean.sum(axis=1).mean():.2f} (SD={df_clean.sum(axis=1).std():.2f})")
    
    # 5. 效标效度(如果有效标数据)
    if demographics:
        print("\n5. 效标效度分析...")
        # 这里需要实际的效标数据
        print("  (需提供效标变量数据)")
    
    # 6. 生成报告
    report = {
        '样本量': len(df_clean),
        'Cronbach_alpha': alpha,
        '因子载荷范围': (loadings.min(), loadings.max()),
        '总分均值': df_clean.sum(axis=1).mean(),
        '总分标准差': df_clean.sum(axis=1).std()
    }
    
    return report

# 使用示例
# report = analyze_cognitive_fusion_questionnaire(df, cfq_items=['CFQ1', 'CFQ2', 'CFQ3', 'CFQ4', 'CFQ5', 'CFQ6', 'CFQ7'])
# print("\n最终报告:")
# print(report)

第十部分:总结与最佳实践

关键要点总结

  1. 数据质量是基础:严格的清洗流程确保分析结果的可靠性
  2. 信度先行:没有良好的信度,效度无从谈起
  3. 理论驱动:所有分析都应基于认知融合的理论框架
  4. 方法透明:详细报告分析过程,便于他人重复和验证
  5. 结果稳健:通过敏感性分析检验结果的稳定性

最佳实践清单

  • [ ] 样本量至少200(EFA)或100(CFA)
  • [ ] 报告完整的信效度指标
  • [ ] 检查测量不变性(多组比较)
  • [ ] 考虑共同方法偏差
  • [ ] 使用多种方法交叉验证结果
  • [ ] 可视化结果便于理解
  • [ ] 保存完整代码和随机种子以便复现

进一步学习资源

  • 书籍:《心理测量学》、《结构方程模型》
  • 软件:R的lavaan包、Mplus、JASP
  • 文献:Gil-lucas et al. (2014) CFQ开发论文
  • 在线课程:Coursera心理测量学课程

通过本指南的系统学习,研究者应能独立完成认知融合问卷的完整分析流程,从数据清洗到高级建模,确保研究的科学性和严谨性。记住,好的分析不仅需要技术技能,更需要对理论和方法的深入理解。# 认知融合问卷怎么分析 从理论到实践的完整指南 包括数据清洗信效度检验与统计建模技巧

引言:认知融合问卷分析的重要性

认知融合(Cognitive Fusion)是接纳与承诺疗法(ACT)中的核心概念,指个体将思想与现实混淆,过度认同内在体验的心理过程。认知融合问卷(如CFQ, Cognitive Fusion Questionnaire)是测量这一构念的常用工具。在心理学研究和临床实践中,对这类问卷进行科学分析至关重要,它直接影响研究结论的可靠性和干预效果的评估。本指南将从理论基础出发,系统阐述从数据清洗到高级统计建模的全流程分析方法,帮助研究者掌握严谨的分析技术。

第一部分:认知融合的理论基础与问卷设计

认知融合的概念框架

认知融合的概念源于关系框架理论(RFT),它描述了人类语言和认知的”衍生关系”特性如何导致心理困扰。当个体将语言等同于现实时,就会产生认知融合,例如将”我感到焦虑”等同于”我是一个焦虑的人”。理解这一理论背景对问卷分析至关重要,因为它决定了问卷应测量的核心维度和潜在的心理结构。

常用认知融合问卷介绍

目前最常用的是Gil-lucas等人开发的CFQ(Cognitive Fusion Questionnaire),包含7个条目,采用7点计分(1=非常不符合,7=非常符合)。例如条目1:”我的想法会让我感到情绪困扰”。其他变体包括简版CFQ-7和针对特定人群的改编版本。了解问卷的结构和计分方式是分析的前提。

1.1 问卷设计的理论依据

认知融合问卷的设计严格遵循ACT理论模型。每个条目都针对特定的认知融合表现:

  • 思维内容融合(如”我必须控制我的想法”)
  • 思维过程融合(如”如果我有负面想法,就意味着我是坏人”)
  • 思维-情绪融合(如”我的想法让我感到痛苦”)

这种理论驱动的设计确保了问卷的内容效度,也为后续的因子分析提供了理论预期。

第二部分:数据清洗与预处理

数据收集与导入

在分析之前,首先需要规范地收集数据。假设我们使用Qualtrics或问卷星等平台收集了500份CFQ问卷数据,导出为CSV格式。使用Python的pandas库进行初步导入:

import pandas as pd
import numpy as np

# 导入数据
df = pd.read_csv('cognitive_fusion_data.csv')

# 查看数据基本信息
print(df.info())
print(df.head())

# 检查数据维度
print(f"数据集包含 {df.shape[0]} 个样本,{df.shape[1]} 个变量")

缺失值处理

缺失值是问卷数据常见问题。需要系统评估缺失模式:

# 计算每个变量的缺失比例
missing_ratio = df.isnull().mean() * 100
print("各变量缺失比例:")
print(missing_ratio)

# 可视化缺失模式
import missingno as msno
msno.matrix(df)

# 根据缺失机制选择处理方法
# 如果是完全随机缺失(MCAR),可以使用删除或均值插补
# 如果是随机缺失(MAR),建议使用多重插补

# 简单删除法(适用于缺失<5%)
df_clean = df.dropna()

# 均值插补(适用于小样本)
df_imputed = df.fillna(df.mean())

# 多重插补(推荐方法)
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

imputer = IterativeImputer(random_state=0)
df_imputed = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)

异常值检测与处理

异常值可能影响统计结果,需要系统检测:

# 方法1:箱线图法检测异常值
import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(12, 6))
sns.boxplot(data=df_imputed)
plt.title('CFQ各条目得分箱线图')
plt.show()

# 方法2:Z分数法(适用于正态分布)
from scipy import stats
z_scores = np.abs(stats.zscore(df_imputed))
outliers = (z_scores > 3).any(axis=1)
print(f"检测到 {outliers.sum()} 个异常值样本")

# 方法3:孤立森林算法(适用于多维数据)
from sklearn.ensemble import IsolationForest
iso_forest = IsolationForest(contamination=0.05, random_state=42)
outlier_labels = iso_forest.fit_predict(df_imputed)
outlier_indices = np.where(outlier_labels == -1)[0]
print(f"孤立森林检测到 {len(outlier_indices)} 个异常值")

# 处理策略:根据理论判断是否删除或Winsorize
# Winsorize处理(将极端值替换为第5/95百分位数)
from scipy.stats.mstats import winsorize
df_winsorized = df_imputed.apply(lambda x: winsorize(x, limits=[0.05, 0.05]))

数据分布检验

检查数据是否符合参数检验的假设:

# 正态性检验(Shapiro-Wilk检验)
for col in df_winsorized.columns:
    stat, p = stats.shapiro(df_winsorized[col])
    print(f"{col}: W={stat:.3f}, p={p:.4f}")
    if p < 0.05:
        print(f"  → 拒绝正态性假设")
    else:
        print(f"  → 接受正态性假设")

# 可视化分布
plt.figure(figsize=(12, 8))
for i, col in enumerate(df_winsorized.columns, 1):
    plt.subplot(2, 4, i)
    sns.histplot(df_winsorized[col], kde=True)
    plt.title(col)
plt.tight_layout()
plt.show()

数据标准化与反向计分

检查问卷是否有反向计分条目并进行转换:

# 假设CFQ的第2、4、6条目是反向计分(实际需根据问卷说明)
reverse_items = ['CFQ2', 'CFQ4', 'CFQ6']

for item in reverse_items:
    if item in df_winsorized.columns:
        # 反向计分:7点计分转换为1-7的反向
        df_winsorized[item] = 8 - df_winsorized[item]
        print(f"已反向计分:{item}")

# 计算总分(如果需要)
df_winsorized['CFQ_Total'] = df_winsorized.sum(axis=1)
print("CFQ总分描述统计:")
print(df_winsorized['CFQ_Total'].describe())

第三部分:信度分析

3.1 内部一致性信度

内部一致性反映问卷各条目测量同一构念的程度:

import pingouin as pg

# 计算Cronbach's Alpha
alpha_result = pg.cronbach_alpha(data=df_winsorized.iloc[:, :7])
print(f"Cronbach's Alpha系数: {alpha_result[0]:.3f}")
print(f"95%置信区间: ({alpha_result[1][0]:.3f}, {alpha_result[1][1]:.3f})")

# 逐项删除后的Alpha值
for item in df_winsorized.columns[:7]:
    alpha_if_deleted = pg.cronbach_alpha(data=df_winsorized.drop(columns=[item]))
    print(f"删除 {item} 后的Alpha: {alpha_if_deleted[0]:.3f}")

# 分半信度(如果问卷条目较多)
# 将条目分为奇偶两部分
odd_items = df_winsorized.columns[0::2]  # 奇数索引
even_items = df_winsorized.columns[1::2]  # 偶数索引

odd_sum = df_winsorized[odd_items].sum(axis=1)
even_sum = df_winsorized[even_items].sum(axis=1)

# Spearman-Brown校正
split_half = pg.corr(odd_sum, even_sum)
r = split_half['r'].values[0]
spearman_brown = (2 * r) / (1 + r)
print(f"分半信度系数(Spearman-Brown校正): {spearman_brown:.3f}")

3.2 重测信度

如果有纵向数据,可以计算重测信度:

# 假设有时间1和时间2的数据
# df_long = pd.read_csv('longitudinal_data.csv')

# 计算皮尔逊相关系数
# retest_corr = pg.corr(df_long['CFQ_T1'], df_long['CFQ_T2'])
# print(f"重测信度: {retest_corr['r'].values[0]:.3f}")

# 如果数据是配对样本,可以使用ICC
# from sklearn.metrics import cohen_kappa_score
# 或使用pingouin的ICC函数
# icc = pg.intraclass_corr(data=df_long, targets='subject', raters='time', ratings='CFQ_score')

3.3 信度结果解读标准

  • Cronbach’s Alpha:>0.7 可接受,>0.8 良好,>0.9 优秀
  • 分半信度:>0.7 可接受
  • 重测信度:>0.7 表明时间稳定性良好

如果信度不达标,需要检查:

  1. 条目是否测量同一构念
  2. 是否存在反向计分错误
  3. 样本量是否足够
  4. 被试是否理解条目含义

第四部分:效度分析

4.1 结构效度:探索性因子分析(EFA)

EFA用于探索问卷的潜在结构:

from factor_analyzer import FactorAnalyzer
from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity
from factor_analyzer.factor_analyzer import calculate_kmo

# 1. 适用性检验
# Bartlett球形检验
chi_square_value, p_value = calculate_bartlett_sphericity(df_winsorized.iloc[:, :7])
print(f"Bartlett球形检验: χ² = {chi_square_value:.2f}, p = {p_value:.4f}")

# KMO检验
kmo_all, kmo_model = calculate_kmo(df_winsorized.iloc[:, :7])
print(f"KMO值: {kmo_model:.3f}")
print("KMO标准: >0.6 可接受,>0.8 良好")

# 2. 因子提取
fa = FactorAnalyzer(n_factors=1, rotation=None)  # 理论预期是单因子结构
fa.fit(df_winsorized.iloc[:, :7])

# 查看因子载荷
loadings = fa.loadings_
print("因子载荷矩阵:")
for i, item in enumerate(df_winsorized.columns[:7]):
    print(f"{item}: {loadings[i, 0]:.3f}")

# 查看公因子方差
communalities = fa.get_communalities()
print("\n公因子方差:")
for i, item in enumerate(df_winsorized.columns[:7]):
    print(f"{item}: {communalities[i]:.3f}")

# 3. 碎石图确定因子数量
fa = FactorAnalyzer(n_factors=7, rotation=None)
fa.fit(df_winsorized.iloc[:, :7])
ev, v = fa.get_eigenvalues()

plt.figure(figsize=(8, 6))
plt.plot(range(1, 8), ev, 'o-')
plt.axhline(y=1, color='r', linestyle='--')
plt.title('碎石图')
plt.xlabel('因子数量')
plt.ylabel('特征值')
plt.show()

# 4. 验证性因子分析(CFA)
import semopy as sem

# 定义模型(单因子模型)
model_spec = """
# 测量模型
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
"""

# 拟合模型
mod = sem.Model(model_spec)
mod.fit(df_winsorized.iloc[:, :7])
print(mod.summary())

# 模型拟合指标
# CFI > 0.9, TLI > 0.9, RMSEA < 0.08, SRMR < 0.08

4.2 效标效度

评估问卷与其他变量的关系:

# 假设我们有焦虑量表(Anxiety)、抑郁量表(Depression)和生活满意度(LifeSat)
# 计算相关矩阵
criteria_vars = ['Anxiety', 'Depression', 'LifeSat']
cfq_vars = df_winsorized.columns[:7]

# 合并数据(假设df_full包含所有变量)
# 相关分析
corr_matrix = df_full[cfq_vars + criteria_vars].corr()
print("CFQ与效标变量的相关矩阵:")
print(corr_matrix.loc[criteria_vars, cfq_vars])

# 绘制热图
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', center=0)
plt.title('CFQ与效标变量相关矩阵')
plt.show()

# 差异检验:高分组 vs 低分组
# 创建高分组(前27%)和低分组(后27%)
cfq_total = df_full[cfq_vars].sum(axis=1)
high_group = df_full[cfq_total > np.percentile(cfq_total, 73)]
low_group = df_full[cfq_total < np.percentile(cfq_total, 27)]

# 比较两组在效标变量上的差异
from scipy.stats import ttest_ind
for var in criteria_vars:
    t_stat, p_val = ttest_ind(high_group[var], low_group[var])
    print(f"{var}: t = {t_stat:.3f}, p = {p_val:.4f}")

4.3 聚合效度与区分效度

# 聚合效度:CFQ与ACT其他核心过程的关系
# 假设我们有接纳量表(AAQ)、正念(FFMQ)等
act_vars = ['AAQ', 'FFMQ', 'Values']
corr_matrix_act = df_full[cfq_vars + act_vars].corr()
print("CFQ与ACT核心过程的相关:")
print(corr_matrix_act.loc[act_vars, cfq_vars])

# 区分效度:CFQ与其他无关构念的关系
# 假设有社会赞许性量表(Marlowe-Crowne)
irrelevant_vars = ['Social_Desirability']
corr_irrelevant = df_full[cfq_vars + irrelevant_vars].corr()
print("\nCFQ与无关构念的相关(应接近0):")
print(corr_irrelevant.loc[irrelevant_vars, cfq_vars])

第五部分:统计建模技巧

5.1 描述性统计与可视化

# 完整描述性统计
desc_stats = df_winsorized.describe()
print(desc_stats)

# 绘制得分分布
plt.figure(figsize=(12, 5))

plt.subplot(1, 2, 1)
sns.histplot(df_winsorized['CFQ_Total'], kde=True, bins=20)
plt.title('CFQ总分分布')
plt.xlabel('总分')
plt.ylabel('频数')

plt.subplot(1, 2, 2)
sns.boxplot(y=df_winsorized['CFQ_Total'])
plt.title('CFQ总分箱线图')
plt.ylabel('总分')

plt.tight_layout()
plt.show()

# 条目得分分布
plt.figure(figsize=(15, 10))
for i, col in enumerate(df_winsorized.columns[:7], 1):
    plt.subplot(2, 4, i)
    sns.countplot(x=df_winsorized[col])
    plt.title(f'条目 {col}')
    plt.xlabel('得分')
    plt.ylabel('频数')
plt.tight_layout()
plt.show()

5.2 组间差异分析

# 独立样本t检验(性别差异)
if 'Gender' in df_full.columns:
    male = df_full[df_full['Gender'] == 'Male']['CFQ_Total']
    female = df_full[df_full['Gender'] == 'Female']['CFQ_Total']
    
    t_stat, p_val = stats.ttest_ind(male, female)
    print(f"性别差异: t({len(male)+len(female)-2}) = {t_stat:.3f}, p = {p_val:.4f}")
    
    # 效应量Cohen's d
    pooled_std = np.sqrt(((len(male)-1)*male.var() + (len(female)-1)*female.var()) / 
                        (len(male)+len(female)-2))
    d = (male.mean() - female.mean()) / pooled_std
    print(f"效应量 d = {d:.3f}")

# 单因素方差分析(年龄组)
if 'Age_Group' in df_full.columns:
    groups = [group['CFQ_Total'].values for name, group in df_full.groupby('Age_Group')]
    f_stat, p_val = stats.f_oneway(*groups)
    print(f"年龄组差异: F = {f_stat:.3f}, p = {p_val:.4f}")
    
    # 事后检验(Tukey HSD)
    from statsmodels.stats.multicomp import pairwise_tukeyhsd
    tukey = pairwise_tukeyhsd(df_full['CFQ_Total'], df_full['Age_Group'])
    print(tukey)

5.3 回归分析预测模型

# 线性回归:预测CFQ得分
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 准备特征矩阵(假设包含人口学变量和预测变量)
features = ['Age', 'Education', 'Anxiety', 'Depression', 'Values']
X = df_full[features]
y = df_full['CFQ_Total']

# 处理分类变量(如有)
X = pd.get_dummies(X, drop_first=True)

# 划分训练测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 拟合模型
lr = LinearRegression()
lr.fit(X_train, y_train)

# 预测与评估
y_pred = lr.predict(X_test)
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f"回归模型性能:")
print(f"均方误差 (MSE): {mse:.3f}")
print(f"R²: {r2:.3f}")

# 查看系数
coef_df = pd.DataFrame({
    '变量': X.columns,
    '系数': lr.coef_,
    '绝对值': np.abs(lr.coef_)
}).sort_values('绝对值', ascending=False)
print("\n回归系数(按重要性排序):")
print(coef_df)

# 使用statsmodels获取详细统计信息
import statsmodels.api as sm
X_sm = sm.add_constant(X_train)
model_sm = sm.OLS(y_train, X_sm).fit()
print(model_sm.summary())

5.4 中介与调节效应分析

# 中介模型:认知融合在ACT核心过程与心理健康间的中介作用
# 使用semopy进行结构方程建模

model_mediation = """
# 测量模型
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
Anxiety =~ Anxiety1 + Anxiety2 + Anxiety3
Depression =~ Depression1 + Depression2 + Depression3
Acceptance =~ AAQ1 + AAQ2 + AAQ3

# 结构模型
CFQ ~ Acceptance
Anxiety ~ CFQ + Acceptance
Depression ~ CFQ + Acceptance

# 间接效应
Acceptance_CFQ_Anx := Acceptance -> CFQ -> Anxiety
Acceptance_CFQ_Dep := Acceptance -> CFQ -> Depression
"""

mod_med = sem.Model(model_mediation)
mod_med.fit(df_full)
print(mod_med.summary())

# Bootstrap检验间接效应
# semopy支持bootstrap,但需要额外配置
# 替代方案:使用process宏或手动bootstrap

# 调节效应:性别调节CFQ与抑郁的关系
model_moderation = """
CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
Depression =~ Depression1 + Depression2 + Depression3
Gender =~ 1*Gender_Male  # 二分变量

# 交互项(需要预先创建)
CFQ_Gender ~ CFQ * Gender
Depression ~ CFQ + Gender + CFQ_Gender
"""

5.5 潜在类别分析(LCA)

识别认知融合的亚群体:

from sklearn.mixture import GaussianMixture
from sklearn.preprocessing import StandardScaler

# 使用CFQ条目进行潜在类别分析
cfq_items = df_winsorized.columns[:7]
X_lca = df_winsorized[cfq_items]

# 标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X_lca)

# 尝试不同类别数
bic_scores = []
aic_scores = []
for n in range(2, 6):
    gmm = GaussianMixture(n_components=n, random_state=42)
    gmm.fit(X_scaled)
    bic_scores.append(gmm.bic(X_scaled))
    aic_scores.append(gmm.aic(X_scaled))

# 绘制信息准则
plt.figure(figsize=(8, 5))
plt.plot(range(2, 6), bic_scores, 'o-', label='BIC')
plt.plot(range(2, 6), aic_scores, 'o-', label='AIC')
plt.xlabel('类别数')
plt.ylabel('信息准则')
plt.title('潜在类别分析:选择最优类别数')
plt.legend()
plt.show()

# 拟合最优模型(假设3类最优)
optimal_n = 3
gmm_optimal = GaussianMixture(n_components=optimal_n, random_state=42)
gmm_optimal.fit(X_scaled)
class_labels = gmm_optimal.predict(X_scaled)

# 分析各类别特征
df_lca = df_winsorized.copy()
df_lca['Class'] = class_labels

print("各类别样本量:")
print(df_lca['Class'].value_counts())

print("\n各类别CFQ总分均值:")
print(df_lca.groupby('Class')['CFQ_Total'].mean())

print("\n各类别在各条目上的特征:")
print(df_lca.groupby('Class')[cfq_items].mean())

5.6 纵向数据分析(如果有重复测量)

# 重复测量ANOVA或混合效应模型
# 假设数据格式:每个被试有时间1、时间2、时间3的CFQ得分

# 使用混合效应模型(推荐)
import statsmodels.formula.api as smf

# 准备长格式数据
# df_long = pd.melt(df_wide, id_vars=['SubjectID'], value_vars=['CFQ_T1', 'CFQ_T2', 'CFQ_T3'],
#                   var_name='Time', value_name='CFQ')

# 混合效应模型
# model = smf.mixedlm("CFQ ~ Time + Group", df_long, groups=df_long["SubjectID"])
# result = model.fit()
# print(result.summary())

# 如果是干预研究,可以比较组间变化
# model = smf.mixedlm("CFQ ~ Time * Group", df_long, groups=df_long["SubjectID"])

第六部分:高级分析技巧与注意事项

6.1 处理非正态分布数据

# 如果数据严重偏态,考虑非参数方法
# Mann-Whitney U检验(替代t检验)
from scipy.stats import mannwhitneyu

# 假设比较高低分组
high_scores = df_full.loc[df_full['CFQ_Total'] > df_full['CFQ_Total'].median(), 'CFQ_Total']
low_scores = df_full.loc[df_full['CFQ_Total'] <= df_full['CFQ_Total'].median(), 'CFQ_Total']

u_stat, p_val = mannwhitneyu(high_scores, low_scores)
print(f"Mann-Whitney U检验: U = {u_stat}, p = {p_val:.4f}")

# Spearman相关(替代Pearson相关)
corr_spearman = df_full[cfq_vars + criteria_vars].corr(method='spearman')
print("Spearman相关矩阵:")
print(corr_spearman)

6.2 共同方法偏差检验

# Harman单因子检验
from factor_analyzer import FactorAnalyzer

# 将所有变量(包括CFQ和效标)放入EFA
all_vars = cfq_vars + criteria_vars
fa_harman = FactorAnalyzer(n_factors=1, rotation=None)
fa_harman.fit(df_full[all_vars])

# 查看第一个因子解释的方差比例
ev, _ = fa_harman.get_eigenvalues()
first_factor_variance = ev[0] / sum(ev)
print(f"第一个因子解释的方差比例: {first_factor_variance:.3f}")

# 如果>40%,可能存在共同方法偏差
if first_factor_variance > 0.4:
    print("警告:可能存在共同方法偏差")
else:
    print("共同方法偏差在可接受范围内")

# 更严格的方法:控制未测量的潜在方法因子(ULMC)
# 需要使用CFA,比较包含和不包含方法因子的模型

6.3 多组比较(测量不变性)

# 检验问卷在不同群体(如性别、文化)中的测量不变性
# 需要使用CFA多组分析

# 1. 形态不变性(Configural Invariance)
# 2. 弱不变性(Metric Invariance)
# 3. 强不变性(Scalar Invariance)
# 4. 严格不变性(Strict Invariance)

# 使用semopy的多组分析功能
# model = """
# CFQ =~ CFQ1 + CFQ2 + CFQ3 + CFQ4 + CFQ5 + CFQ6 + CFQ7
# """

# 分组拟合
# groups = ['Male', 'Female']
# for group in groups:
#     group_data = df_full[df_full['Gender'] == group]
#     mod = sem.Model(model)
#     mod.fit(group_data)

# 比较模型差异(ΔCFI < 0.01 表示不变性成立)

6.4 敏感性分析

# 检验分析结果的稳健性
# 1. 使用不同缺失值处理方法比较结果
methods = ['complete', 'mean', 'median', 'knn']
results = {}

for method in methods:
    if method == 'complete':
        df_method = df.dropna()
    elif method == 'mean':
        df_method = df.fillna(df.mean())
    elif method == 'median':
        df_method = df.fillna(df.median())
    elif method == 'knn':
        from sklearn.impute import KNNImputer
        imputer = KNNImputer(n_neighbors=5)
        df_method = pd.DataFrame(imputer.fit_transform(df), columns=df.columns)
    
    # 计算Alpha
    alpha = pg.cronbach_alpha(data=df_method.iloc[:, :7])[0]
    results[method] = alpha

print("不同缺失值处理方法的Alpha系数:")
for method, alpha in results.items():
    print(f"{method}: {alpha:.3f}")

# 2. 使用不同异常值处理阈值
thresholds = [2.5, 3.0, 3.5]
for thresh in thresholds:
    z_scores = np.abs(stats.zscore(df_imputed))
    outliers = (z_scores > thresh).any(axis=1)
    df_no_outliers = df_imputed[~outliers]
    alpha = pg.cronbach_alpha(data=df_no_outliers.iloc[:, :7])[0]
    print(f"Z阈值={thresh}时的Alpha: {alpha:.3f}")

第七部分:结果报告与解释

7.1 报告标准

根据APA和期刊要求,信效度报告应包括:

  • 信度:Cronbach’s Alpha值、置信区间、条目-总分相关
  • 效度:因子载荷、模型拟合指数(CFI, TLI, RMSEA, SRMR)
  • 效标关联效度:与相关变量的相关系数
  • 测量不变性:多组比较结果

7.2 结果解释示例

# 生成报告摘要
def generate_report(df, cfq_vars):
    report = {}
    
    # 信度
    alpha = pg.cronbach_alpha(data=df[cfq_vars])[0]
    report['Cronbach_alpha'] = alpha
    
    # 描述统计
    report['Mean'] = df[cfq_vars].mean().mean()
    report['SD'] = df[cfq_vars].std().mean()
    
    # 效度(假设已进行CFA)
    # report['CFI'] = 0.95
    # report['RMSEA'] = 0.04
    
    return report

report = generate_report(df_winsorized, cfq_vars)
print("分析结果摘要:")
for key, value in report.items():
    print(f"{key}: {value:.3f}")

7.3 可视化结果

# 创建发表质量的图表
plt.style.use('seaborn-v0_8-whitegrid')
fig, axes = plt.subplots(2, 2, figsize=(12, 10))

# 1. 条目载荷图
loadings = fa.loadings_
axes[0, 0].bar(range(len(loadings)), loadings[:, 0])
axes[0, 0].set_title('因子载荷')
axes[0, 0].set_ylabel('载荷值')
axes[0, 0].set_xticks(range(len(loadings)))
axes[0, 0].set_xticklabels(cfq_vars, rotation=45)

# 2. 效标相关热图
corr_matrix = df_full[cfq_vars + criteria_vars].corr()
sns.heatmap(corr_matrix.loc[criteria_vars, cfq_vars], annot=True, cmap='coolwarm', 
            center=0, ax=axes[0, 1])
axes[0, 1].set_title('效标相关')

# 3. 组间差异
if 'Gender' in df_full.columns:
    sns.boxplot(data=df_full, x='Gender', y='CFQ_Total', ax=axes[1, 0])
    axes[1, 0].set_title('性别差异')

# 4. 回归系数
coef_df = pd.DataFrame({'变量': X.columns, '系数': lr.coef_})
sns.barplot(data=coef_df, x='系数', y='变量', ax=axes[1, 1])
axes[1, 1].set_title('回归系数')

plt.tight_layout()
plt.savefig('cognitive_fusion_analysis.png', dpi=300, bbox_inches='tight')
plt.show()

第八部分:常见问题与解决方案

8.1 信度不达标

问题:Alpha < 0.7

解决方案

  1. 检查反向计分是否正确
  2. 删除低相关条目(item-total correlation < 0.3)
  3. 增加样本量
  4. 考虑问卷是否适合当前人群
# 识别低相关条目
item_total_corr = []
for item in cfq_vars:
    corr = pg.corr(df_winsorized[item], df_winsorized['CFQ_Total'])
    item_total_corr.append(corr['r'].values[0])

low_corr_items = [item for i, item in enumerate(cfq_vars) if item_total_corr[i] < 0.3]
print("低相关条目(r < 0.3):", low_corr_items)

8.2 CFA模型拟合不佳

问题:CFI < 0.9 或 RMSEA > 0.08

解决方案

  1. 检查因子载荷是否<0.4
  2. 考虑添加残差相关
  3. 检查数据是否有多维结构
  4. 考虑使用修正指数(Modification Indices)
# 识别低载荷条目
low_loadings = [item for i, item in enumerate(cfq_vars) if abs(loadings[i, 0]) < 0.4]
print("低载荷条目(<0.4):", low_loadings)

8.3 样本量不足

问题:样本量 < 100

解决方案

  1. 使用Bootstrap重抽样
  2. 采用贝叶斯方法
  3. 报告置信区间而非仅p值
  4. 考虑使用简版问卷

8.4 数据非正态

问题:Shapiro-Wilk检验p < 0.05

解决方案

  1. 使用非参数检验
  2. 数据转换(如对数、平方根)
  3. 使用稳健标准误
  4. 增加样本量(中心极限定理)

第九部分:完整分析流程示例

从原始数据到最终报告

# 完整流程封装
def analyze_cognitive_fusion_questionnaire(df, cfq_items, demographics=None):
    """
    完整分析CFQ问卷的函数
    
    参数:
    df: 原始数据DataFrame
    cfq_items: CFQ条目名称列表
    demographics: 人口学变量列表
    """
    
    print("="*60)
    print("认知融合问卷完整分析流程")
    print("="*60)
    
    # 1. 数据清洗
    print("\n1. 数据清洗...")
    # 缺失值处理
    missing_rate = df[cfq_items].isnull().mean().mean()
    print(f"  平均缺失率: {missing_rate:.2%}")
    
    if missing_rate > 0.05:
        print("  → 使用多重插补")
        from sklearn.experimental import enable_iterative_imputer
        from sklearn.impute import IterativeImputer
        imputer = IterativeImputer(random_state=0)
        df_imputed = pd.DataFrame(imputer.fit_transform(df[cfq_items]), columns=cfq_items)
    else:
        df_imputed = df[cfq_items].dropna()
    
    # 异常值检测
    z_scores = np.abs(stats.zscore(df_imputed))
    outliers = (z_scores > 3).any(axis=1)
    print(f"  异常值样本: {outliers.sum()} 个")
    df_clean = df_imputed[~outliers]
    
    # 2. 信度分析
    print("\n2. 信度分析...")
    alpha = pg.cronbach_alpha(data=df_clean)[0]
    print(f"  Cronbach's Alpha: {alpha:.3f}")
    
    if alpha < 0.7:
        print("  → 信度不达标,检查数据质量")
    else:
        print("  → 信度良好")
    
    # 3. 效度分析(EFA)
    print("\n3. 效度分析(探索性因子分析)...")
    from factor_analyzer import FactorAnalyzer
    fa = FactorAnalyzer(n_factors=1, rotation=None)
    fa.fit(df_clean)
    loadings = fa.loadings_
    
    print("  因子载荷:")
    for i, item in enumerate(cfq_items):
        print(f"    {item}: {loadings[i,0]:.3f}")
    
    # 4. 描述性统计
    print("\n4. 描述性统计...")
    desc = df_clean.describe()
    print(f"  总分均值: {df_clean.sum(axis=1).mean():.2f} (SD={df_clean.sum(axis=1).std():.2f})")
    
    # 5. 效标效度(如果有效标数据)
    if demographics:
        print("\n5. 效标效度分析...")
        # 这里需要实际的效标数据
        print("  (需提供效标变量数据)")
    
    # 6. 生成报告
    report = {
        '样本量': len(df_clean),
        'Cronbach_alpha': alpha,
        '因子载荷范围': (loadings.min(), loadings.max()),
        '总分均值': df_clean.sum(axis=1).mean(),
        '总分标准差': df_clean.sum(axis=1).std()
    }
    
    return report

# 使用示例
# report = analyze_cognitive_fusion_questionnaire(df, cfq_items=['CFQ1', 'CFQ2', 'CFQ3', 'CFQ4', 'CFQ5', 'CFQ6', 'CFQ7'])
# print("\n最终报告:")
# print(report)

第十部分:总结与最佳实践

关键要点总结

  1. 数据质量是基础:严格的清洗流程确保分析结果的可靠性
  2. 信度先行:没有良好的信度,效度无从谈起
  3. 理论驱动:所有分析都应基于认知融合的理论框架
  4. 方法透明:详细报告分析过程,便于他人重复和验证
  5. 结果稳健:通过敏感性分析检验结果的稳定性

最佳实践清单

  • [ ] 样本量至少200(EFA)或100(CFA)
  • [ ] 报告完整的信效度指标
  • [ ] 检查测量不变性(多组比较)
  • [ ] 考虑共同方法偏差
  • [ ] 使用多种方法交叉验证结果
  • [ ] 可视化结果便于理解
  • [ ] 保存完整代码和随机种子以便复现

进一步学习资源

  • 书籍:《心理测量学》、《结构方程模型》
  • 软件:R的lavaan包、Mplus、JASP
  • 文献:Gil-lucas et al. (2014) CFQ开发论文
  • 在线课程:Coursera心理测量学课程

通过本指南的系统学习,研究者应能独立完成认知融合问卷的完整分析流程,从数据清洗到高级建模,确保研究的科学性和严谨性。记住,好的分析不仅需要技术技能,更需要对理论和方法的深入理解。