如何以Pythonic方式将大型Pandas邻接矩阵转成长格式?
大型邻接矩阵转长格式的高效实现
针对你的7500×7500邻接矩阵(仅20万非零值)转长格式时的内存问题,以下是两种更Pythonic且内存友好的方案:
方案1:利用Pandas stack() 结合内存优化
stack() 是Pandas官方推荐的宽转长方法,配合数据类型压缩可以大幅降低内存占用:
- 压缩数据类型:邻接矩阵的数值通常不需要高精度,先将
float64转为float32(甚至float16,如果精度允许),直接减少一半内存开销:
import pandas as pd # 压缩数据类型,降低内存占用 df = df.astype('float32')
- 转长格式并过滤非零值:
# stack() 将列索引转为行级索引,生成多级索引的Series long_series = df.stack() # 重置索引并过滤非零记录 long_df = long_series.reset_index() long_df = long_df[long_df[0] != 0] # 重命名列名,符合业务逻辑 long_df.columns = ['source', 'target', 'weight']
方案2:基于稀疏矩阵的高效提取
由于你的矩阵是高稀疏性(非零值占比仅~0.35%),直接用scipy稀疏矩阵处理内存效率最高,完全避免生成中间全量数据:
import scipy.sparse as sp # 将DataFrame转为CSR稀疏矩阵(适合行维度的非零值提取) sparse_mat = sp.csr_matrix(df.values) # 获取所有非零值的行、列索引和对应数值 rows, cols = sparse_mat.nonzero() weights = sparse_mat.data # 映射回原DataFrame的索引和列名,生成最终长格式DataFrame long_df = pd.DataFrame({ 'source': df.index[rows], 'target': df.columns[cols], 'weight': weights })
为什么这两种方法更Pythonic?
- 避免手动循环,利用Pandas/scipy的底层C语言优化逻辑,运行速度远快于纯Python循环
- 代码简洁易读,符合Python"优雅、简洁"的设计原则
- 内存效率更高,尤其是稀疏矩阵方案,仅处理非零值相关数据,内存占用极低
内容的提问来源于stack exchange,提问作者R Walser
相关产品推荐
相关产品推荐

