2012-01-26 17 views
1

trimmedまたはwinsorizedリストの標準偏差を計算する効率的な方法は何ですか?トリム/ winsorized標準偏差

私はnumpyを使用しても構いませんが、リストの別のコピーを作成する必要がある場合は、かなり遅くなります。

答えて

1

これは2つのコピーを作成しますが、非常に高速であるため試してください。

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には、2回のパスとカウントが必要です。このため、ベースコレクションの一部のイテレータを「tee」する必要があります。

So.

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倍遅いです:(普通のPythonのオーバーヘッドがコピーよりもずっと遅くなっていると思います... – max

+1

8倍遅く!これはnumpyの値を示しています –

1

偏りのないトリミングされた平均を得るためには、hereと記載されているようにリスト内の項目の小数ビットを考慮する必要があります(少し直接的ではありません)here。私もそれを実証an iPython Notebookを作っ

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) 

:私はそれを行うための機能を書きました。

私の機能はおそらく、すでに投稿されているものよりも遅くなりますが、不偏な結果が得られます。