стандартное отклонение - PullRequest
       19

стандартное отклонение

1 голос
/ 26 января 2012

Какой эффективный способ вычисления усеченного или winsorized стандартного отклонения списка?

Я не против использовать numpy, но если мне придется сделать отдельную копию списка, это будет довольно медленно.

Ответы [ 3 ]

1 голос
/ 26 января 2012

Это сделает две копии, но вы должны попробовать, потому что это должно быть очень быстро.

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 быстрее, чем все, что я мог придумать.

1 голос
/ 27 июня 2013

Чтобы получить несмещенное усеченное среднее, вы должны учитывать дробные биты элементов в списке, как описано здесь и (чуть менее прямо) здесь . Я написал функцию, чтобы сделать это:

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 )

Я также сделал ноутбук iPython , который демонстрирует это.

Моя функция, вероятно, будет медленнее, чем уже опубликованные, но даст непредвзятые результаты.

1 голос
/ 26 января 2012

Для этого предназначены функции генератора.

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

Нечто подобное может делать то, что вы хотите, не копируя ничего.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...