使用values和counts绘制直方图遇MemoryError,求优化方案
高效绘制带频次的直方图(避免内存溢出)
你遇到的问题是因为np.repeat会生成规模达21亿+的超大数组,远超内存承载能力——完全没必要重建原始数据,直接利用频次信息即可绘制直方图,以下是两种高效实现方式:
方法一:利用matplotlib hist的weights参数(最简洁)
matplotlib的hist函数本身支持weights参数,直接传入每个数值对应的频次,函数会自动基于权重计算各区间的总频次,无需生成原始数据数组:
import numpy as np import matplotlib.pyplot as plt values = [1, 2, 2.5, 4, 5, 5.75, 6.5] counts = [10**8, 10**9, 1.5*10**7, 1.25*10**7, 10**6, 10**7, 10**9] f1, ax = plt.subplots(1,1) # 传入values和对应的weights参数,直接生成直方图 ax.hist(values, bins=5, weights=counts) plt.show()
方法二:手动计算区间频次后绘制柱状图(更灵活)
如果需要更精细地控制直方图的生成逻辑,可以手动计算每个bin的总频次,再用bar绘制:
import numpy as np import matplotlib.pyplot as plt values = [1, 2, 2.5, 4, 5, 5.75, 6.5] counts = np.array([10**8, 10**9, 1.5*10**7, 1.25*10**7, 10**6, 10**7, 10**9]) # 定义5个bin的边界 bins = np.linspace(min(values), max(values), 5 + 1) # 确定每个value所属的bin索引 bin_indices = np.digitize(values, bins) - 1 # 计算每个bin的总频次 bin_total_counts = np.bincount(bin_indices, weights=counts, minlength=len(bins)-1) f1, ax = plt.subplots(1,1) # 绘制柱状图,宽度为bin的区间长度 ax.bar(bins[:-1], bin_total_counts, width=np.diff(bins)) plt.show()
这两种方法都不会生成超大数组,内存占用仅取决于values和counts的长度,完全解决内存溢出问题。
内容的提问来源于stack exchange,提问作者pkj
相关产品推荐
相关产品推荐

