在 x 范围内运行 y 值的中位数
Posted
技术标签:
【中文标题】在 x 范围内运行 y 值的中位数【英文标题】:Running median of y-values over a range of x 【发布时间】:2014-06-06 17:24:08 【问题描述】:下面是我从两个 numpy 数组构建的散点图。
散点图示例
我想添加到该图中的是 y 在 x 范围内的运行中位数。我已经在一个示例中进行了 Photoshop 处理:
修改散点图
具体来说,我需要两个值之间沿 x 轴 1 个单位的箱中的数据点的中位数(这个范围在许多图之间会有所不同,但我可以手动调整它)。我感谢任何可以为我指明正确方向的提示。
【问题讨论】:
相邻 bin 中的 y 值集之间是否存在依赖关系或相关性?除非有,否则您必须对每组应用标准中位数计算。 不,每个 bin 都可以单独处理。为了计算图中的整体中位数,我在所有 y 值上使用了 pylab.median。不幸的是,我不确定如何将这些值分解为 x 范围内的特定大小的 bin。一旦我克服了这个障碍,我就可以对每个 bin 重复计算中值。 【参考方案1】:我会使用 np.digitize
为您进行 bin 排序。这样您就可以轻松应用任何功能并设置您感兴趣的范围。
import numpy as np
import pylab as plt
N = 2000
total_bins = 10
# Sample data
X = np.random.random(size=N)*10
Y = X**2 + np.random.random(size=N)*X*10
bins = np.linspace(X.min(),X.max(), total_bins)
delta = bins[1]-bins[0]
idx = np.digitize(X,bins)
running_median = [np.median(Y[idx==k]) for k in range(total_bins)]
plt.scatter(X,Y,color='k',alpha=.2,s=2)
plt.plot(bins-delta/2,running_median,'r--',lw=4,alpha=.8)
plt.axis('tight')
plt.show()
作为该方法通用性的示例,让我们添加由每个 bin 的标准差给出的误差线:
running_std = [Y[idx==k].std() for k in range(total_bins)]
plt.errorbar(bins-delta/2,running_median,
running_std,fmt=None)
【讨论】:
太好了。感谢您也提供了一些额外的东西!【参考方案2】:这个问题也可以通过python pandas(Python数据分析库)有效解决,提供原生的数据切割和分析方法。
考虑一下
(感谢 @Hooked 并为他的示例 +1,我从中借用了 X
和 Y
数据)
import pandas as pd
df = pd.DataFrame('X' : X, 'Y' : Y) #we build a dataframe from the data
data_cut = pd.cut(df.X,bins) #we cut the data following the bins
grp = df.groupby(by = data_cut) #we group the data by the cut
ret = grp.aggregate(np.median) #we produce an aggregate representation (median) of each bin
#plotting
plt.scatter(df.X,df.Y,color='k',alpha=.2,s=2)
plt.plot(ret.X,ret.Y,'r--',lw=4,alpha=.8)
plt.show()
备注:这里红色曲线的x值是bin-wise x-median(可以使用bin的中点)。
【讨论】:
很棒的方法。我尝试了所有的建议,每一个都很好。谢谢!【参考方案3】:您可以基于numpy.median()
创建一个函数,该函数将计算给定区间的中值:
import numpy as np
def medians(x, y, intervals):
out = []
for xmin, xmax in intervals:
mask = (x >= xmin) & (x < xmax)
out.append(np.median(y[mask]))
return np.array(out)
然后使用此函数获得所需的间隔:
import matplotlib.pyplot as plt
intervals = ((18, 19), (19, 20), (20, 21), (21, 22))
centers = [(xmin+xmax)/2. for xmin, xmax in intervals]
plt.plot(centers, medians(x, y, intervals)
【讨论】:
很棒的方法。我尝试了所有的建议,每一个都很好。谢谢! 如果间隔是连续的,您可以使用 itertools 成对配方:intervals = pairwise((18, 19, 20, 21, 22))
或 pairwise(range(18, 23, 1))
【参考方案4】:
我在C#
中写过类似的内容。我不做 Python 所以这里是伪代码:
List
用于从中派生中位数的数据
按x
值对散点图点进行排序
按x
值循环排序点
对于每个点,将该点的Y
值插入到中值列表中,以便中值列表作为排序列表增长。即插入 Y,使其上方和下方的 List 值分别为 > 和 Inserting values into specific locations in a list in Python。
每个Y
值添加后,中间值将是当前中间索引处的列表值,即List(List.Length/2)
希望对你有帮助!
【讨论】:
以上是关于在 x 范围内运行 y 值的中位数的主要内容,如果未能解决你的问题,请参考以下文章