2011-02-10 5 views
13

통계 작업을하고 있는데 평균을 계산할 난수가 많이 있습니다. 생성자를 계산해야하기 때문에 생성자와 작업하고 싶습니다. 의미, 그래서 번호를 저장할 필요가 없습니다.파이썬에서 생성자에 대한 평균을 계산합니다.

문제는 생성기를 전달할 때 numpy.mean이 중단된다는 것입니다. 내가 원하는 것을하기위한 간단한 함수를 작성할 수는 있지만, 이것을하기위한 적절한 기본 제공 방법이 있는지 궁금합니다.

"합계 (값)/len (값)"이라고 말할 수 있으면 좋겠지 만 len은 유전자 변형기에서 작동하지 않으며 이미 소비 된 값을 합친 것입니다.

import numpy 

def my_mean(values): 
    n = 0 
    Sum = 0.0 
    try: 
     while True: 
      Sum += next(values) 
      n += 1 
    except StopIteration: pass 
    return float(Sum)/n 

X = [k for k in range(1,7)] 
Y = (k for k in range(1,7)) 

print numpy.mean(X) 
print my_mean(Y) 

이 모두 같은, 올바른 대답을 my_mean 나열 작동하지 않습니다 구입하고 numpy.mean은 발전기 작동하지 않습니다

여기 예입니다.

저는 발전기로 작업한다는 아이디어를 정말 좋아하지만, 이와 같은 세부 사항은 상황을 망칠 수 있습니다.

+2

당신은 당신의 발전기 생산 얼마나 많은 난수 알고있는 것을, 당신은하지 않을까요? –

+0

@Sven Marnach : 발전기가 파일을 읽는다고 가정합니다. – Jimmy

+1

정말로 데이터를 저장하고 싶지 않고 (더 느린'sum' 함수를 구현하지 않는다면) 계산 생성기를 생성하고 다음과 같이 호출 할 수 있습니다 :'co = countingGen(); 평균 = 합계 (co (data))/co.getCount()' –

답변

5

코드를 한 번만 변경하면 두 가지를 모두 사용할 수 있습니다. 생성자는 for-loop의 목록과 상호 교환하여 사용하기위한 것입니다.

def my_mean(values): 
    n = 0 
    Sum = 0.0 
    for v in values: 
     Sum += v 
     n += 1 
    return Sum/n 
+2

Sum과 같은 대문자는 일반적으로 클래스 용으로 예약되어 있습니다. – xApple

+0

@xApple,이 질문에있는 코드와 비슷하게 만들려고했습니다. 변수가 'Sum'이라는 이름으로 표시됩니다. 개인적으로 나는 PEP 8의 대회를 따라 갔을 것입니다. –

+2

그리고'sum'은 내장되어 있으므로'sum_' 또는'total'을 사용해야합니다 –

-1

시도 :

import itertools 

def mean(i): 
    (i1, i2) = itertools.tee(i, 2) 
    return sum(i1)/sum(1 for _ in i2) 

print mean([1,2,3,4,5]) 

tee 당신이 합산 및 계산에 대한 다른 하나 개 중복을 사용할 수 있도록, 모든 반복 가능한 i (예를 들어, 발전기, 목록 등)에 대한 반복자를 복제합니다.

('tee'는 여전히 중간 저장 공간을 사용합니다.)

+2

이것은 전체 목록을 임시로 저장합니다. 메모리 방식으로, 그것은리스트로 먼저 변환하고'sum (a)/len (a) '을 사용하는 것과 같습니다. 그러나 목록을 사용하는 것이 더 빠릅니다. –

+0

좋은 지적, 사실 - 나는 tee()가 어떻게 구현되는지를보고 있었다. 그 일이 생길 때 나는 그것을 싫어한다. :-) – payne

+0

'tee'는 복제 된 반복자, 즉 하나는 소비했지만 다른 하나는 아직 사용하지 않은 요소들 사이에 "diff"를 저장함으로써 구현 될 수 있다고 생각할 것입니다. –

1

한 가지 방법은

numpy.fromiter(Y, int).mean() 

것이다 그러나 이것은 실제로 일시적으로 번호를 저장합니다.

0
def my_mean(values): 
    n = 0 
    sum = 0 
    for v in values: 
     sum += v 
     n += 1 
    return sum/n 

위는 목록 또는 반복자를 얻는 경우에 당신이 상관없이 좋은 values을 반복하는 for를 사용하여 제외하고, 코드와 매우 유사하다. 그러나 파이썬 sum 메서드는 매우 최적화되어 있으므로 목록이 실제로 길지 않으면 임시로 데이터를 저장하는 것이 더 행복 할 수 있습니다.

(또한 당신이 python3를 사용하고 있기 때문에, 당신은 float(sum)/n 필요가 없다는 것을 알) 당신이 StopIteration를 얻을 때까지

+1

'sum = 0'을하면 내장 함수를 마스킹합니다. – xApple

1

당신의 접근 방식은 좋은 일이지만, 대신 반복적으로 next를 호출하는 대신 for x in y 관용구를 사용한다 . 이것은 목록과 생성자 모두에 적용됩니다.

def my_mean(values): 
    n = 0 
    Sum = 0.0 

    for value in values: 
     Sum += value 
     n += 1 
    return float(Sum)/n 
+0

'Sum'과 같은 대문자는 일반적으로 클래스 용으로 예약되어 있습니다. – xApple

3

구식 방법은 그것을 할 수 있습니다 : _sum() 정확한 합계를 반환

def mean(data): 
    if iter(data) is data: 
     data = list(data) 
    n = len(data) 
    if n < 1: 
     raise StatisticsError('mean requires at least one data point') 
    return _sum(data)/n 

(math.fsum() -like 기능 :

def my_mean(values): 
    sum, n = 0, 0 
    for x in values: 
     sum += x 
     n += 1 
    return float(sum)/n 
4
def my_mean(values): 
    total = 0 
    for n, v in enumerate(values, 1): 
     total += v 
    return total/n 

print my_mean(X) 
print my_mean(Y) 

statistics.mean() in Python 3.4하지만 it calls list() on the input있다 그 외에도 float도 지원합니다. s Fraction, Decimal). 당신이 사전에 발전기의 길이를 알고 당신이 메모리에 전체 목록을 저장하지 않도록하려면

+0

'enumerate'에 더한 것이 하나 있습니다 - 가장 파이썬적인 방법 인 IMO입니다. – Tgsmith61591

0

, 당신은 사용할 수 있습니다 : 일반적으로

reduce(np.add, generator)/length 
14

당신이 스트리밍을하고있는 경우 부동의 계산을 의미 소수점 숫자를 사용하는 경우 생성기를 합산하고 길이로 나누는 것보다 더 수치 안정성이 좋은 알고리즘을 사용하는 것이 좋습니다.

가장 간단한 것 (알고있는 것)은 일반적으로 credited to Knuth이며 분산을 계산합니다. 이 링크에는 파이썬 구현이 포함되어 있지만, 여기에는 완전한 부분 만 복사됩니다.

def mean(data): 
    n = 0 
    mean = 0.0 

    for x in data: 
     n += 1 
     mean += (x - mean)/n 

    if n < 1: 
     return float('nan'); 
    else: 
     return mean 

나는이 질문은 매우 오래 알고 있지만, 여전히 구글의 첫 번째 히트, 그래서 그것을 게시 할 적절한 것 같았다. 파이썬 표준 라이브러리에이 간단한 코드 조각이 포함되어 있지 않다는 사실은 여전히 ​​슬픈 일입니다.

0

당신은 배열의 크기 모르게 줄일 사용할 수 있습니다

from itertools import izip, count 
reduce(lambda c,i: (c*(i[1]-1) + float(i[0]))/i[1], izip(values,count(1)),0) 
관련 문제