在 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,我从中借用了 XY 数据)

 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 值的中位数的主要内容,如果未能解决你的问题,请参考以下文章

P1889SOLDIERS (中位数)

课堂测试——数据位数位数输出各位数上数据求和

算法66------计算各个位数不同的数字个数动态规划

编写程序:输入一个4位的整数,然后分别输出组成改4位数的各位数字。

根据百分位数绘制直方图

D. Range and Partition