【问题标题】:Finding appropriate cut-off values寻找合适的临界值
【发布时间】:2011-03-07 09:41:04
【问题描述】:

我尝试实现Hampel tanh estimators 来规范化高度不对称的数据。为此,我需要执行以下计算:

鉴于x - 一个排序的数字列表和m - x 的中位数,我需要找到a 使得x 中大约70% 的值落入@987654330 范围内@。我们对x 中的值分布一无所知。我使用 numpy 在 python 中编写,我最好的想法是编写某种随机迭代搜索(例如,如Solis and Wets 所述),但我怀疑有更好的方法,或者以更好的算法或作为现成的功能。我搜索了 numpy 和 scipy 文档,但找不到任何有用的提示。

编辑

Sethsuggested 使用 scipy.stats.mstats.trimboth,但是在我对倾斜分布的测试中,这个建议不起作用:

from scipy.stats.mstats import trimboth
import numpy as np

theList = np.log10(1+np.arange(.1, 100))
theMedian = np.median(theList)

trimmedList = trimboth(theList, proportiontocut=0.15)
a = (trimmedList.max() - trimmedList.min()) * 0.5

#check how many elements fall into the range
sel = (theList > (theMedian - a)) * (theList < (theMedian + a))

print np.sum(sel) / float(len(theList))

输出为 0.79(~80%,而不是 70)

【问题讨论】:

  • 你说你对分布一无所知,但想要一个关于中位数对称的范围。这并不完全一致。
  • 迈克尔,我希望我在问题开头的澄清能回答你的问题
  • 是的,这很好地阐明了意图。

标签: python algorithm numpy scipy sampling


【解决方案1】:

您首先需要通过将所有小于平均值的值向右折叠来对称分布。然后你可以在这个单向分布上使用标准的scipy.stats 函数:

from scipy.stats import scoreatpercentile
import numpy as np

theList = np.log10(1+np.arange(.1, 100))
theMedian = np.median(theList)

oneSidedList = theList[:]               # copy original list
# fold over to the right all values left of the median
oneSidedList[theList < theMedian] = 2*theMedian - theList[theList < theMedian]

# find the 70th centile of the one-sided distribution
a = scoreatpercentile(oneSidedList, 70) - theMedian

#check how many elements fall into the range
sel = (theList > (theMedian - a)) * (theList < (theMedian + a))

print np.sum(sel) / float(len(theList))

这会根据需要给出0.7 的结果。

【讨论】:

    【解决方案2】:

    稍微重述问题。您知道列表的长度,以及要考虑的列表中数字的比例。鉴于此,您可以确定列表中为您提供所需范围的第一个和最后一个索引之间的差异。然后,目标是找到将最小化与所需的关于中位数的对称值相对应的成本函数的索引。

    设较小的索引为n1,较大的索引为n2;这些不是独立的。索引列表中的值是x[n1] = m-bx[n2]=m+c。您现在要选择n1(因此选择n2),以便bc 尽可能接近。当(b - c)**2 最小时会发生这种情况。使用numpy.argmin 非常容易。与问题中的示例平行,这是一个说明该方法的交互式会话:

    $ python
    Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
    [GCC 4.3.4 20090804 (release) 1] on cygwin
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import numpy as np
    >>> theList = np.log10(1+np.arange(.1, 100))
    >>> theMedian = np.median(theList)
    >>> listHead = theList[0:30]
    >>> listTail = theList[-30:]
    >>> b = np.abs(listHead - theMedian)
    >>> c = np.abs(listTail - theMedian)
    >>> squaredDiff = (b - c) ** 2
    >>> np.argmin(squaredDiff)
    25
    >>> listHead[25] - theMedian, listTail[25] - theMedian
    (-0.2874888056626983, 0.27859407466756614)
    

    【讨论】:

      【解决方案3】:

      你想要的是scipy.stats.mstats.trimboth。设置proportiontocut=0.15。修剪后,取(max-min)/2

      【讨论】:

      • 赛斯:谢谢你的提示。不知道这个功能。但是,正如您在我添加到问题中的示例中所见,Space_C0wb0y 是正确的:此方法不适用于倾斜数据。
      • @Space_C0wb0y- 抱歉。你的评论是正确的。值偏移量将取决于分布形状
      猜你喜欢
      • 2016-12-13
      • 2010-09-11
      • 2021-02-15
      • 1970-01-01
      • 2011-01-13
      • 1970-01-01
      • 1970-01-01
      • 2022-08-04
      • 1970-01-01
      相关资源
      最近更新 更多