Pandas新手疑问:如何创建全列交叉频数统计表用于热图绘制?
嗨,我来帮你搞定这个问题!首先得明确:你要的是一个列名×列名的矩阵,每个单元格对应一对列的交叉频数统计结果,这样才能用Seaborn画热图展示列之间的计数关联对吧?之前用pd.crosstab只处理了单对列,所以没得到想要的全局格式,接下来我一步步教你实现:
第一步:数据准备(PySpark转Pandas)
先把PySpark的DataFrame转成Pandas的(如果你的机器内存够处理60万行70列的话),代码很简单:
df_pd = df_spark.toPandas()
如果内存吃紧,建议直接用PySpark做交叉统计(后面会说优化方案)。
第二步:生成列×列的交叉计数矩阵
我们要创建一个和原列数一致的空矩阵,然后遍历所有列对,把每对列的交叉频数统计结果填进去。这里我以交叉表中的最大计数值为例(你可以换成自己需要的统计量,比如非零组合数、总计数等):
import pandas as pd import itertools # 获取所有列名 cols = df_pd.columns # 创建空的N×N矩阵(N是列数) cross_count_matrix = pd.DataFrame(0, index=cols, columns=cols) # 遍历所有列对(用combinations_with_replacement减少一半计算量,因为(col1,col2)和(col2,col1)的交叉表是转置的) for col1, col2 in itertools.combinations_with_replacement(cols, 2): # 计算两列的交叉频数表 ctab = pd.crosstab(df_pd[col1], df_pd[col2]) # 提取你需要的统计量:这里取交叉表中的最大计数 stat_value = ctab.max().max() # 填充矩阵(对称位置赋值,因为交叉表转置后统计量一致) cross_count_matrix.loc[col1, col2] = stat_value cross_count_matrix.loc[col2, col1] = stat_value
第三步:用Seaborn画热图
有了矩阵之后,画热图就很简单了,记得调整图的大小适配70列的宽度:
import seaborn as sns import matplotlib.pyplot as plt plt.figure(figsize=(18, 15)) # 70列需要足够大的画布 sns.heatmap(cross_count_matrix, annot=True, cmap="YlGnBu", fmt="d", cbar=True) plt.title("Cross Frequency Statistics Between Column Pairs") plt.tight_layout() plt.show()
大数据优化方案(PySpark直接处理)
如果60万行70列转Pandas内存不够,直接用PySpark做交叉统计,再把结果汇总到Pandas矩阵里:
from pyspark.sql import SparkSession import itertools spark = SparkSession.builder.appName("CrossTabBigData").getOrCreate() df_spark = spark.read.csv("hdfs://your/hdfs/path", header=True, inferSchema=True) cols = df_spark.columns cross_count_matrix = pd.DataFrame(0, index=cols, columns=cols) for col1, col2 in itertools.combinations_with_replacement(cols, 2): # PySpark计算交叉表 ctab_spark = df_spark.crosstab(col1, col2) # 转成Pandas处理统计量 ctab_pd = ctab_spark.toPandas() # 提取最大计数(注意PySpark交叉表的第一列是col1的类别,其他列是col2的类别) stat_value = ctab_pd.iloc[:, 1:].max().max() cross_count_matrix.loc[col1, col2] = stat_value cross_count_matrix.loc[col2, col1] = stat_value
自定义统计量
你可以根据需求替换stat_value的计算逻辑:
- 交叉表非零组合数:
(ctab > 0).sum().sum() - 交叉表总计数:
ctab.sum().sum()(其实就是行数,意义不大) - 交叉表均值:
ctab.mean().mean()
这样就能得到你想要的交叉频数统计矩阵,完美适配Seaborn热图啦!
内容的提问来源于stack exchange,提问作者whs2k
相关产品推荐
相关产品推荐

