[PYTHON] numpy를 사용하는 가중 백분위 수
PYTHONnumpy를 사용하는 가중 백분위 수
가중 백분위를 계산하기 위해 numpy.percentile 함수를 사용하는 방법이 있습니까? 아니면 가중치 백분위를 계산하는 파이썬 함수를 알고있는 사람이 있습니까?
감사!
해결법
-
==============================
1.안타깝게도 numpy는 모든 것에 대해 가중 함수를 내장하지 않지만 언제나 함께 사용할 수 있습니다.
안타깝게도 numpy는 모든 것에 대해 가중 함수를 내장하지 않지만 언제나 함께 사용할 수 있습니다.
def weight_array(ar, weights): zipped = zip(ar, weights) weighted = [] for i in zipped: for j in range(i[1]): weighted.append(i[0]) return weighted np.percentile(weight_array(ar, weights), 25)
-
==============================
2.여기에 제가 사용하고있는 코드가 있습니다. 그것은 최적의 것이 아닙니다 (나는 numpy로 쓸 수 없습니다). 그러나 여전히 받아 들여진 해결책보다 훨씬 빠르고 신뢰할 수 있습니다.
여기에 제가 사용하고있는 코드가 있습니다. 그것은 최적의 것이 아닙니다 (나는 numpy로 쓸 수 없습니다). 그러나 여전히 받아 들여진 해결책보다 훨씬 빠르고 신뢰할 수 있습니다.
def weighted_quantile(values, quantiles, sample_weight=None, values_sorted=False, old_style=False): """ Very close to numpy.percentile, but supports weights. NOTE: quantiles should be in [0, 1]! :param values: numpy.array with data :param quantiles: array-like with many quantiles needed :param sample_weight: array-like of the same length as `array` :param values_sorted: bool, if True, then will avoid sorting of initial array :param old_style: if True, will correct output to be consistent with numpy.percentile. :return: numpy.array with computed quantiles. """ values = numpy.array(values) quantiles = numpy.array(quantiles) if sample_weight is None: sample_weight = numpy.ones(len(values)) sample_weight = numpy.array(sample_weight) assert numpy.all(quantiles >= 0) and numpy.all(quantiles <= 1), 'quantiles should be in [0, 1]' if not values_sorted: sorter = numpy.argsort(values) values = values[sorter] sample_weight = sample_weight[sorter] weighted_quantiles = numpy.cumsum(sample_weight) - 0.5 * sample_weight if old_style: # To be convenient with numpy.percentile weighted_quantiles -= weighted_quantiles[0] weighted_quantiles /= weighted_quantiles[-1] else: weighted_quantiles /= numpy.sum(sample_weight) return numpy.interp(quantiles, weighted_quantiles, values)
예 :
배열 ([1., 3.2, 9.])
배열 ([1., 3.2, 9.])
-
==============================
3.첫 번째 정렬 및 보간을 통한 빠른 솔루션 :
첫 번째 정렬 및 보간을 통한 빠른 솔루션 :
def weighted_percentile(data, percents, weights=None): ''' percents in units of 1% weights specifies the frequency (count) of data. ''' if weights is None: return np.percentile(data, percents) ind=np.argsort(data) d=data[ind] w=weights[ind] p=1.*w.cumsum()/w.sum()*100 y=np.interp(percents, p, d) return y
-
==============================
4.추가 (독창적 인) 답변에 대한 사과 (@ nayyarv에 대한 의견을 말할 수있는 담당자가 충분하지 않음). 그의 솔루션은 나를 위해 일했습니다. (즉, np.percentage의 기본 동작을 복제합니다.)하지만 원래의 np.percentage가 어떻게 작성되었는지 단서가있는 for 루프를 제거 할 수 있다고 생각합니다.
추가 (독창적 인) 답변에 대한 사과 (@ nayyarv에 대한 의견을 말할 수있는 담당자가 충분하지 않음). 그의 솔루션은 나를 위해 일했습니다. (즉, np.percentage의 기본 동작을 복제합니다.)하지만 원래의 np.percentage가 어떻게 작성되었는지 단서가있는 for 루프를 제거 할 수 있다고 생각합니다.
def weighted_percentile(a, q=np.array([75, 25]), w=None): """ Calculates percentiles associated with a (possibly weighted) array Parameters ---------- a : array-like The input array from which to calculate percents q : array-like The percentiles to calculate (0.0 - 100.0) w : array-like, optional The weights to assign to values of a. Equal weighting if None is specified Returns ------- values : np.array The values associated with the specified percentiles. """ # Standardize and sort based on values in a q = np.array(q) / 100.0 if w is None: w = np.ones(a.size) idx = np.argsort(a) a_sort = a[idx] w_sort = w[idx] # Get the cumulative sum of weights ecdf = np.cumsum(w_sort) # Find the percentile index positions associated with the percentiles p = q * (w.sum() - 1) # Find the bounding indices (both low and high) idx_low = np.searchsorted(ecdf, p, side='right') idx_high = np.searchsorted(ecdf, p + 1, side='right') idx_high[idx_high > ecdf.size - 1] = ecdf.size - 1 # Calculate the weights weights_high = p - np.floor(p) weights_low = 1.0 - weights_high # Extract the low/high indexes and multiply by the corresponding weights x1 = np.take(a_sort, idx_low) * weights_low x2 = np.take(a_sort, idx_high) * weights_high # Return the average return np.add(x1, x2) # Sample data a = np.array([1.0, 2.0, 9.0, 3.2, 4.0], dtype=np.float) w = np.array([2.0, 1.0, 3.0, 4.0, 1.0], dtype=np.float) # Make an unweighted "copy" of a for testing a2 = np.repeat(a, w.astype(np.int)) # Tests with different percentiles chosen q1 = np.linspace(0.0, 100.0, 11) q2 = np.linspace(5.0, 95.0, 10) q3 = np.linspace(4.0, 94.0, 10) for q in (q1, q2, q3): assert np.all(weighted_percentile(a, q, w) == np.percentile(a2, q))
-
==============================
5.weighted 백분위가 무엇인지 알지는 못하지만 @Joan Smith의 대답에서 보면 ar의 모든 요소를 반복하면 numpy.repeat ()를 사용할 수 있습니다.
weighted 백분위가 무엇인지 알지는 못하지만 @Joan Smith의 대답에서 보면 ar의 모든 요소를 반복하면 numpy.repeat ()를 사용할 수 있습니다.
import numpy as np np.repeat([1,2,3], [4,5,6])
결과는 다음과 같습니다.
array([1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3])
-
==============================
6.내 필요에이 기능을 사용합니다.
내 필요에이 기능을 사용합니다.
def quantile_at_values(values, population, weights=None): values = numpy.atleast_1d(values).astype(float) population = numpy.atleast_1d(population).astype(float) # if no weights are given, use equal weights if weights is None: weights = numpy.ones(population.shape).astype(float) normal = float(len(weights)) # else, check weights else: weights = numpy.atleast_1d(weights).astype(float) assert len(weights) == len(population) assert (weights >= 0).all() normal = numpy.sum(weights) assert normal > 0. quantiles = numpy.array([numpy.sum(weights[population <= value]) for value in values]) / normal assert (quantiles >= 0).all() and (quantiles <= 1).all() return quantiles
quantile 대신 백분위 수가 필요한 경우 결과에 100을 곱하십시오.
-
==============================
7.의견에서 언급했듯이 단순히 float 가중치에서는 값을 반복 할 수 없으며 매우 큰 데이터 집합에서는 실용적이지 않습니다. 여기에 가중 백분위 수를 나타내는 라이브러리가 있습니다. http://www.google.com/intl/ko 그것은 나를 위해 일했습니다.
의견에서 언급했듯이 단순히 float 가중치에서는 값을 반복 할 수 없으며 매우 큰 데이터 집합에서는 실용적이지 않습니다. 여기에 가중 백분위 수를 나타내는 라이브러리가 있습니다. http://www.google.com/intl/ko 그것은 나를 위해 일했습니다.
-
==============================
8.
def weighted_percentile(a, percentile = np.array([75, 25]), weights=None): """ O(nlgn) implementation for weighted_percentile. """ percentile = np.array(percentile)/100.0 if weights is None: weights = np.ones(len(a)) a_indsort = np.argsort(a) a_sort = a[a_indsort] weights_sort = weights[a_indsort] ecdf = np.cumsum(weights_sort) percentile_index_positions = percentile * (weights.sum()-1)+1 # need the 1 offset at the end due to ecdf not starting at 0 locations = np.searchsorted(ecdf, percentile_index_positions) out_percentiles = np.zeros(len(percentile_index_positions)) for i, empiricalLocation in enumerate(locations): # iterate across the requested percentiles if ecdf[empiricalLocation-1] == np.floor(percentile_index_positions[i]): # i.e. is the percentile in between 2 separate values uppWeight = percentile_index_positions[i] - ecdf[empiricalLocation-1] lowWeight = 1 - uppWeight out_percentiles[i] = a_sort[empiricalLocation-1] * lowWeight + \ a_sort[empiricalLocation] * uppWeight else: # i.e. the percentile is entirely in one bin out_percentiles[i] = a_sort[empiricalLocation] return out_percentiles
이것은 내 기능이며, 동일한 동작을 제공합니다.
np.percentile(np.repeat(a, weights), percentile)
메모리 오버 헤드가 적습니다. np.percentile은 O (n) 구현이므로 작은 가중치의 경우 더 빠를 수도 있습니다. 그것은 모든 엣지 케이스를 분류 해 놓았습니다. 정확한 해결책입니다. 위의 보간 답변은 가중치가 1 인 경우를 제외하고 대부분의 경우 단계 일 때 선형이라고 가정합니다.
무게 [3, 11, 7]로 데이터 [1,2,3]가 있고 25 % 백분위 수를 원한다고 가정 해보십시오. 내 ecdf는 [3, 10, 21]이 될 것이며 5 번째 값을 찾고 있습니다. 보간법은 [3,1]과 [10,2]가 일치하는 것으로보고 보간법을 적용하여 2 번째 빈에 완전히 있음에도 불구하고 1.28을 내 보냅니다.
-
==============================
9.여기 내 해결책 :
여기 내 해결책 :
def my_weighted_perc(data,perc,weights=None): if weights==None: return nanpercentile(data,perc) else: d=data[(~np.isnan(data))&(~np.isnan(weights))] ix=np.argsort(d) d=d[ix] wei=weights[ix] wei_cum=100.*cumsum(wei*1./sum(wei)) return interp(perc,wei_cum,d)
단순히 데이터의 가중 CDF를 계산 한 다음 가중 백분위 수를 계산하는 데 사용합니다.
from https://stackoverflow.com/questions/21844024/weighted-percentile-using-numpy by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] Python에서 저렴한 예외 처리 기능을 제공합니까? (0) | 2018.11.20 |
---|---|
[PYTHON] SSL : Python3을 사용하여 CERTIFICATE_VERIFY_FAILED (0) | 2018.11.20 |
[PYTHON] 파일에서 읽은 목록의 줄 바꿈 문자 제거 [duplicate] (0) | 2018.11.20 |
[PYTHON] 대소 문자 무시 문자열에서 부분 문자열을 일치시키는 방법은 무엇입니까? (0) | 2018.11.20 |
[PYTHON] Python 정규식, 여러 줄에 걸쳐 패턴 일치. 왜이 코드가 작동하지 않습니까? (0) | 2018.11.20 |