복붙노트

[PYTHON] 그 값을 기반으로 배열의 누피 합계 요소

PYTHON

그 값을 기반으로 배열의 누피 합계 요소

정렬되지 않은 배열이 있습니다.

i = np.array([1,5,2,6,4,3,6,7,4,3,2])

같은 길이의 값 배열도 있습니다.

v = np.array([2,5,2,3,4,1,2,1,6,4,2])

원하는 값이 0으로 배열되어 있습니다.

d = np.zeros(10)

이제 i의 인덱스에 따라 v의 d 값으로 요소를 추가하고 싶습니다.

내가 평범한 파이썬에서 그렇게한다면 나는 이렇게 할 것이다 :

for index,value in enumerate(v):
    idx = i[index]
    d[idx] += v[index]

추악하고 비효율적입니다. 어떻게 변경할 수 있습니까?

해결법

  1. ==============================

    1.우리는 np.bincount를 사용할 수 있는데, 이것은 누적 가중치 계산에 꽤 효율적일 것입니다. 그래서 여기에 그 중 하나가 있습니다 -

    우리는 np.bincount를 사용할 수 있는데, 이것은 누적 가중치 계산에 꽤 효율적일 것입니다. 그래서 여기에 그 중 하나가 있습니다 -

    counts = np.bincount(i,v)
    d[:counts.size] = counts
    

    양자 택일로, minlength 입력 인수를 사용하고 d가 임의의 배열이 될 수 있고 일반적인 경우에 우리가 그것에 추가하기를 원할 때 -

    d += np.bincount(i,v,minlength=d.size).astype(d.dtype, copy=False)
    

    런타임 테스트

    이 섹션에서는 다른 게시물에 나열된 np.add.at 기반 접근 방식과이 게시물 앞부분에 나열된 np.bincount 기반 접근 방식을 비교합니다.

    In [61]: def bincount_based(d,i,v):
        ...:     counts = np.bincount(i,v)
        ...:     d[:counts.size] = counts
        ...: 
        ...: def add_at_based(d,i,v):
        ...:     np.add.at(d, i, v)
        ...:     
    
    In [62]: # Inputs (random numbers)
        ...: N = 10000
        ...: i = np.random.randint(0,1000,(N))
        ...: v = np.random.randint(0,1000,(N))
        ...: 
        ...: # Setup output arrays for two approaches
        ...: M = 12000
        ...: d1 = np.zeros(M)
        ...: d2 = np.zeros(M)
        ...: 
    
    In [63]: bincount_based(d1,i,v) # Run approaches
        ...: add_at_based(d2,i,v)
        ...: 
    
    In [64]: np.allclose(d1,d2)  # Verify outputs
    Out[64]: True
    
    In [67]: # Setup output arrays for two approaches again for timing
        ...: M = 12000
        ...: d1 = np.zeros(M)
        ...: d2 = np.zeros(M)
        ...: 
    
    In [68]: %timeit add_at_based(d2,i,v)
    1000 loops, best of 3: 1.83 ms per loop
    
    In [69]: %timeit bincount_based(d1,i,v)
    10000 loops, best of 3: 52.7 µs per loop
    
  2. ==============================

    2.

    np.add.at(d, i, v)
    

    당신은 d [i] + = v가 작동한다고 생각할 것입니다.하지만 동일한 방법으로 여러 셀을 추가하려고하면 그 중 하나가 다른 셀을 오버라이드합니다. ufunc.at 메소드는 이러한 문제점을 피합니다.

  3. from https://stackoverflow.com/questions/33818113/numpy-sum-elements-in-array-based-on-its-value by cc-by-sa and MIT license