Python中mca包多对应分析疑问:新数据转换及属性含义
解决MCA转换新数据的问题&属性解释
我之前也遇到过类似的困扰,mca包确实没有内置的transform方法,但我们可以基于MCA的数学原理手动实现转换。另外你提到的属性命名晦涩、.L全1的问题,大概率是因为用了drop_first=True生成哑变量导致的,先从这里说起:
首先修正输入错误
MCA要求输入完整的指示矩阵:每个分类变量的所有类别都要作为列,每个样本在每个变量的类别列中恰好有一个1(其余为0),这样每个样本的行和等于原始数据的变量数。drop_first=True会移除每个变量的一个类别,导致部分样本的行和减少,进而让MCA计算出现异常(比如你看到的.L全1)。修正后的训练代码如下:
import pandas as pd import mca import numpy as np # 示例训练数据 df = pd.DataFrame({ 'color': ['red', 'blue', 'green', 'red', 'blue'], 'size': ['small', 'large', 'small', 'large', 'small'] }) # 生成完整哑变量矩阵,不要加drop_first=True! df_dummy = pd.get_dummies(df) ca = mca.MCA(df_dummy)
一、手动实现新数据的转换
mca包没有现成的转换方法,但我们可以基于MCA的核心逻辑自己写,步骤如下:
核心逻辑
MCA的样本因子得分(ca.fs_r(n))是通过标准化后的指示矩阵左乘训练得到的右奇异向量得到的。转换新数据时,需要对新数据做和训练数据完全一致的标准化,再用训练好的奇异向量投影。
具体代码实现
# 示例新数据 df_new = pd.DataFrame({ 'color': ['green', 'red', 'blue'], 'size': ['large', 'small', 'large'] }) # 1. 生成和训练数据完全匹配的哑变量矩阵,缺失列填充0 df_new_dummy = pd.get_dummies(df_new).reindex(columns=df_dummy.columns, fill_value=0) # 2. 计算新数据的行和(每个样本的变量数,这里是2) row_sum_new = df_new_dummy.sum(axis=1).values.reshape(-1, 1) # 3. 计算期望矩阵E_new:用训练数据的列和 + 新数据的行和计算 E_new = np.outer(row_sum_new, ca.col_sum.values) / ca.total # 4. 标准化得到Z_new:(观测值 - 期望值) / sqrt(期望值) Z_new = (df_new_dummy.values - E_new) / np.sqrt(E_new) # 5. 投影得到新数据的因子得分(取前2个主成分) n_components = 2 new_scores = Z_new @ ca.Vt.T[:, :n_components] # 验证:训练数据的因子得分和ca.fs_r(n_components)一致 train_scores = ca.fs_r(n_components) print("训练数据得分:\n", train_scores) print("新数据得分:\n", new_scores)
二、晦涩属性/方法的含义
mca包的命名确实偏简洁,我整理了常用属性的实际意义:
.E:期望矩阵,基于训练数据的行和、列和计算,每个元素是(行和 × 列和) / 总样本数,代表独立假设下每个单元格的期望频数。.L:特征值,等于ca.S ** 2 / ca.total,每个值对应一个主成分的解释力,值越大代表该主成分能解释的方差越多(之前全1是因为drop_first=True导致输入错误)。.K:原始数据的变量总数(比如你的df有多少列)。.k:每个变量的类别数量列表,比如[3,2]代表第一个变量有3个类别,第二个有2个。.U:左奇异向量,对应样本(行)的正交向量,和奇异值结合可得到因子得分。.S:奇异值,是标准化矩阵Z的奇异值,和特征值的关系是特征值 = S² / 总样本数。.Vt:右奇异向量的转置,对应类别(列)的正交向量,用于计算样本的因子得分。.fs_r(n):样本的因子得分,取前n个主成分,等价于ca.U[:, :n] * ca.S[:n]。.fs_c(n):类别的因子得分,取前n个主成分,用于可视化类别在主成分空间的位置。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

