如何用Python对二维数据沿x轴进行指数分箱?
实现指数分箱并计算分箱内y值的平均值
没问题!要实现你说的这种在log-log尺度上呈线性的指数分箱(也就是每个分箱是100~101、101~102这类对数区间),核心是先生成对数间距的分箱边界,再把x值分配到对应分箱,最后计算每个分箱内y值的平均值。下面是具体的步骤和代码示例:
步骤1:生成对数间距的分箱边界
我们用numpy.logspace()来生成等对数间距的分箱边界,它能直接帮你生成10a到10b之间的均匀对数间隔点。比如你想从100到103分3个箱,边界就是[1,10,100,1000]:
import numpy as np # 替换成你自己的x(入度)和y(出度)数组 x = np.random.uniform(1, 1000, 1000) # 模拟入度数据 y = np.random.uniform(0.1, 100, 1000) # 模拟出度数据 # 定义分箱参数:你可以根据自己的数据调整这些值 min_log = 0 # 分箱起始的对数(对应10^0) max_log = 3 # 分箱结束的对数(对应10^3) num_bins = 3 # 分箱数量 # 生成对数间距的分箱边界 bin_edges = np.logspace(min_log, max_log, num_bins + 1)
步骤2:把x值分配到对应分箱
用numpy.digitize()就能快速得到每个x值所属的分箱索引:
# 获取每个x对应的分箱索引(索引从1开始,对应第一个分箱是bin_edges[0]~bin_edges[1]) bin_indices = np.digitize(x, bin_edges)
步骤3:计算每个分箱内y值的平均值
这里给你两种实现方式,按需选择:
方法一:纯Numpy实现(不需要额外库)
bin_means = [] for i in range(1, num_bins + 1): # 筛选出当前分箱内的所有y值 y_in_bin = y[bin_indices == i] if len(y_in_bin) > 0: bin_means.append(np.mean(y_in_bin)) else: bin_means.append(np.nan) # 空分箱填充NaN,避免后续绘图报错 # 计算分箱的中心值(用于绘图,几何均值更适合log尺度) bin_centers = np.sqrt(bin_edges[:-1] * bin_edges[1:])
方法二:用Pandas更简洁实现(代码更直观)
如果你平时用Pandas处理数据,分组计算会更省心:
import pandas as pd # 把数据转成DataFrame df = pd.DataFrame({'入度': x, '出度': y}) # 给每个x值分配分箱 df['分箱'] = pd.cut(df['入度'], bins=bin_edges) # 分组计算每个分箱的出度均值 bin_stats = df.groupby('分箱')['出度'].mean().reset_index() # 计算分箱中心值用于绘图 bin_stats['分箱中心'] = bin_stats['分箱'].apply(lambda interval: np.sqrt(interval.left * interval.right))
步骤4:绘制分箱后的log-log图
最后把原始数据和分箱后的结果画出来对比,就能看到平滑后的关系了:
import matplotlib.pyplot as plt plt.loglog(x, y, 'o', alpha=0.3, label='原始数据') plt.loglog(bin_centers, bin_means, 's-', color='darkred', label='分箱均值') plt.xlabel('入度') plt.ylabel('出度') plt.legend() plt.title('网络同配性(入度-出度)分箱图') plt.show()
为什么不用np.hist/plt.hist?
你说得完全对!np.hist和plt.hist默认是统计每个分箱内的样本数量(频数),而我们需要的是对y值做聚合计算(求均值),所以上面的方法更贴合你的需求。
如果需要调整分箱的精细度,只要修改num_bins参数就行,比如改成5个分箱,就能得到更细的对数区间啦。
内容的提问来源于stack exchange,提问作者antimornings
相关产品推荐
相关产品推荐

