什么是计算列表trimmed或winsorized标准偏差的有效方法?
我不介意使用numpy
,但如果我必须单独制作一份列表,那么它会很慢。
答案 0 :(得分:1)
这就是生成器功能的用途。
SD要求两次通过,加上一次计数。因此,您需要在基础集合上“开发”一些迭代器。
所以
trimmed = ( x for x in the_list if low <= x < high )
sum_iter, len_iter, var_iter = itertools.tee( trimmed, 3 )
n = sum( 1 for x in len_iter)
mean = sum( sum_iter ) / n
sd = math.sqrt( sum( (x-mean)**2 for x in var_iter ) / (n-1) )
这样的东西可能会做你想要的而不复制任何东西。
答案 1 :(得分:1)
这将制作两份副本,但你应该试一试,因为它应该非常快。
def trimmed_std(data, low, high):
tmp = np.asarray(data)
return tmp[(low <= tmp) & (tmp < high)].std()
您是否需要进行排名修剪(即5%修剪)?
更新
如果你需要百分位修剪,我能想到的最好方法是先对数据进行排序。这样的事情应该有效:
def trimmed_std(data, percentile):
data = np.array(data)
data.sort()
percentile = percentile / 2.
low = int(percentile * len(data))
high = int((1. - percentile) * len(data))
return data[low:high].std(ddof=0)
你可以在不使用numpy的情况下实现这一点,但即使包括将列表转换为数组的时间,使用numpy也比我想象的要快。
答案 2 :(得分:1)
为了获得无偏差的修剪均值,您必须按照here和(稍微不那么直接)here来描述列表中项目的小数位。我写了一个函数来做到这一点:
def percent_tmean( data, pcent ):
# make sure data is a list
dc = list( data )
# find the number of items
n = len(dc)
# sort the list
dc.sort()
# get the proportion to trim
p = pcent / 100.0
k = n*p
# print "n = %i\np = %.3f\nk = %.3f" % ( n,p,k )
# get the decimal and integer parts of k
dec_part, int_part = modf( k )
# get an index we can use
index = int(int_part)
# trim down the list
dc = dc[ index: index * -1 ]
# deal with the case of trimming fractional items
if dec_part != 0.0:
# deal with the first remaining item
dc[ 0 ] = dc[ 0 ] * (1 - dec_part)
# deal with last remaining item
dc[ -1 ] = dc[ -1 ] * (1 - dec_part)
return sum( dc ) / ( n - 2.0*k )
我还制作了展示它的an iPython Notebook。
我的功能可能会比已发布的功能慢,但会产生无偏见的结果。