2012-01-26 6 views
1

목록의 trimmed 또는 winsorized 표준 편차를 계산하는 효율적인 방법은 무엇을 winsorized?은/손질 표준 편차

나는 numpy를 사용하여 상관 없어,하지만 난 목록의 별도의 복사본을 만들 경우, 아주 느린 것입니다.

답변

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는 두 개의 패스 플러스 카운트가 필요합니다. 이러한 이유로 기본 컬렉션보다 일부 반복자를 "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 배 더 느립니다. (일반 파이썬 오버 헤드가 복사보다 훨씬 느려지는 것 같습니다 ... – max

+1

8 배 느리게! numpy의 값을 보여줍니다. 꽤 starkly. –

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) 

: 나는 그것을 할 수있는 기능을 썼다.

내 기능은 아마 이미 게시보다 느립니다하지만 공정한 결과를 제공 할 것입니다.

관련 문제