找到合适的截止值

我尝试实现Hampel tanh估计器来规范化高度不对称的数据。为此,我需要执行以下计算: 给定
x
- 排序的数字列表和
m
-
x
的中位数,我需要找到
a
,使得
x
中大约70%的值落入
(m-a; m+a)
的范围内。我们对
x
中的价值分布一无所知。我使用numpy在python中编写,我最好的想法是编写某种随机迭代搜索(例如,如Solis和Wets所描述的),但我怀疑有更好的方法,无论是以形式还是更好的算法或准备好的功能。我搜索了numpy和scipy文档,但找不到任何有用的提示。 编辑 Seth建议使用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)     
已邀请:
您需要首先通过将小于平均值的所有值折叠到右侧来对称分布。然后,您可以在此单边分布上使用标准
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
的结果。     
稍微重述一下这个问题。您知道列表的长度,以及要考虑的列表中的数字部分。鉴于此,您可以确定列表中为您提供所需范围的第一个和最后一个索引之间的差异。然后,目标是找到将最小化与期望的关于中值的对称值相对应的成本函数的指数。 让较小的指数为
n1
,指数较大的指数为
n2
;这些不是独立的。指数列表中的值为
x[n1] = m-b
x[n2]=m+c
。您现在要选择
n1
(因此
n2
),以便
b
c
尽可能接近。当
(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)
    
你想要的是scipy.stats.mstats.trimboth。设置
proportiontocut=0.15
。修剪后,取
(max-min)/2
。     

要回复问题请先登录注册