2017-12-02 1 views
1

숫자가인 축이 (before, at, after)이고 축이 axis 인 축이 arr 인 축을 다시 형성하고 싶습니다. 이 작업을 더 빠르게 수행하는 방법은 무엇입니까?축의 전후에 축을 합치십시오.

는 축이 정상화되었습니다 0 <= axis < arr.ndim

프로그램 :

import numpy as np 
def f(arr, axis): 
    shape = arr.shape 
    before = int(np.product(shape[:axis])) 
    at = shape[axis] 
    return arr.reshape(before, at, -1) 

테스트 :

a = np.arange(2 * 3 * 4 * 5).reshape(2, 3, 4, 5) 
print(f(a, 2).shape) 

결과 : 당신의 축이 MIDD에 정말

(6, 4, 5) 
+0

퍼센트의 timeit을 (F를 (a, 2) .shape) 루프 당 489 NS ± 8.14 μS (평균 ± 표준 편차는 7 회, 각 루프는 100000 회) 속도에 정말로 관심이 있습니까? ;) – NaN

+0

금요일 밤에 나는 지루해하거나 강박 신경증이라고 생각한다. 'arr + = np.arange (arr.size, dtype = arr.dtype) '과 같은 것은 같은 의미로 약간 미친 짓이지만 많은 사람들이 그렇게합니다. 그것은 C++에서 단순한 루프 일뿐입니다 ... –

+0

reduceat를 루프 당 5.08 μs ± 234 ns (평균 ± 표준 편차 7 회, 각각 루프 100000 회) 사용하므로 손에 더 많은 시간을 갖게됩니다.) – NaN

답변

2

shape은 튜플이며 원하는 결과는 튜플입니다. 배열을 변환하여 np.prod 또는 다른 배열 함수를 사용하려면 시간이 걸립니다. 따라서 우리가 평범한 파이썬 코드로 동일한 작업을 수행 할 수 있다면 시간을 절약 할 수 있습니다. 예를 들어

shape과 :

In [309]: shape 
Out[309]: (2, 3, 4, 5) 
In [310]: np.prod(shape) 
Out[310]: 120 
In [311]: functools.reduce(operator.mul,shape) 
Out[311]: 120 

In [312]: timeit np.prod(shape) 
13.6 µs ± 30.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 
In [313]: timeit functools.reduce(operator.mul,shape) 
647 ns ± 12.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 

파이썬 버전은 눈에 띄게 빠르다. functoolsoperator을 가져와 sum (Python3)의 곱셈을 얻었습니다.

또는 새로운 모양 튜플 얻을 :

In [314]: axis=2 
In [315]: (functools.reduce(operator.mul,shape[:axis]),shape[axis],-1) 
Out[315]: (6, 4, -1) 
In [316]: timeit (functools.reduce(operator.mul,shape[:axis]),shape[axis],-1) 
739 ns ± 30.4 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each) 

reduceat 제안 비교 :

In [318]: tuple(np.multiply.reduceat(shape, (0, axis, axis+1))) 
Out[318]: (6, 4, 5) 
In [319]: timeit tuple(np.multiply.reduceat(shape, (0, axis, axis+1))) 
11.3 µs ± 21.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each) 
+0

이니셜 라이저를 사용하면 axis = 0으로 작업 할 수 있습니다. '(functools.reduce (operator.mul, shape [: axis], 1), shape [축], - 1)'https://stackoverflow.com/questions/33945882/reduce-function-doesnt-handle-an- 비어있는 목록 –

+0

@hpaulj 나는 그것을 사용할지도 모른다 ;-) –

+0

@hamsteronwheels는 여전히 왼쪽에 어색한 1을 삽입한다. OTOH, 어떤 경우에는 바람직 할 수도 있습니다. –

1

경우 당신이 제로 번째 또는 마지막 축 당신이 특별한 경우에해야합니다 제작 : 당신은하지만, np.multiply.reduceat

shape = (2, 3, 4, 5, 6) 
axis = 2 
np.multiply.reduceat(shape, (0, axis, axis+1)) 
# array([ 6, 4, 30]) 
axis = 3 
np.multiply.reduceat(shape, (0, axis, axis+1)) 
# array([24, 5, 6]) 

를 사용할 수 있습니다.