2014-09-15 3 views
1

numpy에서 특정 사용 사례를 코드화하는 우아한 (또는보다 우아한) 방법을 찾고 있습니다. 유스 케이스는 100 개 이상의 필드, 1,000 개가 넘는 코드 및 여러 개의 코드 섹션으로 구성된 대규모 데이터 세트 (효율성 문제)로 필드의 하위 집합 만 처리하려고합니다. 만큼 내가 모든 관측치를 처리하고있어,이 일반 NumPy와의 깨끗하고 효율적입니다 : 나는 말에 대한 관찰의 서브 세트 만, 코드의 30 개 라인을 처리 할여러 줄에 마스크 적용 (구문 설탕?)

wages = np.arange(40000,60000,2000) 
cg = np.arange(0,100000,10000) 
ded = np.repeat([6000,9000],5) 
exem = np.repeat([2000,4000],5) 

agi = wages + cg 
tinc = agi - ded 
tinc = tinc - exem 

그러나 많은 코드 부절 및 이것이 내가 가지고 올 수있는 최선입니다 : 끔찍한 아니다

agi = wages + cg 
mask = wages < 50001 
tinc = agi 

tinc[mask] = agi[mask] - ded[mask] 
tinc[mask] = tinc[mask] - exem[mask] 

, 오해하지만, 변수의 수백 및 수백 줄의 코드에 의해이 번식하지 않습니다. cython/numba 루프를 사용하지 않고 다음과 같은 작업을 수행 할 수 있습니까? 즉

# fake code, just to convey the desired syntax 
agi = wages + cg 
tinc = agi 

mask(wages < 50001): # i.e. inside a python loop, would be "if wages < 50001:" 
    tinc = agi - ded 
    tinc = tinc - exem 

, 내가 명시 적으로 모든 단독 어레이의 마스크를 입력 할 필요없이 코드의 하위 섹션을 정의하고 동일한 마스크 코드 섹션 내의 모든 단일 배열에 적용하도록 지정하고 싶습니다.

은 (, BTW 나는 NumPy와를 통해 내 최고의 옵션을 탐구하는 것을 선호가 팬더를 통해 몇 가지 대안 접근 할 수 있지만, 지금은 할 수 있습니다 알고있다. 나중에에 판다 태그이 질문을 다시 요청할 수 있습니다.)

답변

1

나는 이것을 권장하지는 않지만 ... 일 수 있습니다. 끔찍한 마술 컨텍스트 매니저로 처리하십시오. 예를 들어 :

@contextlib.contextmanager 
def masking(namespace, mask): 
    # If you don't have a fixed set of maskable variables, make it 
    # an instance/global/local variables, like `_names`, or just 
    # [name for name, value in namespace.items() if isiinstance(value, np.ndarray)] 
    names = 'tinc agi dec exem'.split() 
    stash = {name: namespace[name] for name in names} 
    for name in names: 
     namespace[name] = namespace[name][mask] 
    try: 
     yield 
    finally: 
     for name in names: 
      namespace[name] = stash[name] 

이제 당신은이 작업을 수행 할 수 있습니다이 Numpy's masked arrays을 사용 할 수있다하기에 관하여 갈

with masking(globals(), wages < 50001): 
    tinc = agi - dec 
    tinc = tinc - exem 

with masking(self.__dict__, self.wages < 50001): 
    self.tinc = self.agi - self.dec 
    self.tinc = self.tinc - self.exem 

# etc. 
+0

그래,이 작업을 수행할지 여부를 결정해야합니다. 그러나 numpy에서 유일하게일지도 모른다. 감사! – JohnE

0

한 가지 방법.

Numpy의 설명서가 더 자세히 설명되어 있으므로 시작하기 전에 살펴 보시기 바랍니다. 아마도 복잡성이 더해질 수 있습니다 (function under numpy.ma을 사용해야 할 수도 있고 사용하지 않을 수도 있습니다). 코드의 모든 작업이 여전히 정확하도록주의해야하지만 마스크 된 배열을 사용하면 쉽게 정의 할 수 있습니다. 이 같은 맥락 관리자 : 마스킹 작업에-장소로 가지고 있기 때문에, 당신이 함께 일하는 배열로 시작하는 마스크 배열이라는 것을 필요로

@contextlib.contextmanager 
def mask(clause, masked_arrays): 
    for ma in masked_arrays: 
     ma[~clause] = np.ma.masked 
    yield 
    for ma in masked_arrays: 
     ma.mask = np.ma.nomask 

참고. 그러면 다음과 같이 쉽게 사용할 수 있습니다.

# Wrap arrays as masked arrays 
mwages = np.ma.array(wages) 
mcg = np.ma.array(cg) 
... etc ... 

with mask(mwages < 50001, [mwages, mcg, mded, ...]): 
    # np.ma.compressed returns 1D array of non-masked items 
    unmasked_tinc = np.ma.compressed(magi - mded - mexem) 

    # or must change the masked one directly