2012-01-26 27 views

回答

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的是比任何我能想到的速度更快。

+0

是的,我需要進行排序(百分比)修整,這就是爲什麼我特別關心時間:我需要再次傳遞一次,以確定保留原始列表的哪些值。 – max

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)) 

類似的東西可能會做你想要的,而不需要複製任何東西。

+0

這樣做,但不知何故,它比複製到numpy的陣列較慢的8倍:(我想經常蟒蛇開銷減慢東西比一個副本下來更多... – max

+1

8倍慢!這表明'numpy'的價值很顯然 –

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演示它。

我的功能可能會比已發佈的功能慢,但它會給公正的結果。