2016-03-28 14 views
3

xが与えられた場合、x, log(x)をnumpy配列として生成すると、xの形状はsになり、結果は形状が(*s, 2)になります。これを行うための最も素敵な方法は何ですか? xはちょうどフロートかもしれません。その場合は、形状が(2,)の結果が必要です。効率的な配列配列の作成

これを行うには醜い方法は、次のとおりです。

import numpy as np 

x = np.asarray(x) 
result = np.empty((*x.shape, 2)) 
result[..., 0] = x 
result[..., 1] = np.log(x) 

答えて

4

それはパフォーマンスの美学を分離することが重要です。時には醜いコードは です。実際、ここがそうです。空の配列を作成してから スライスに値を代入すると美しく見えない場合がありますが、高速です。

import numpy as np 
import timeit 
import itertools as IT 
import pandas as pd 

def using_empty(x): 
    x = np.asarray(x) 
    result = np.empty(x.shape + (2,)) 
    result[..., 0] = x 
    result[..., 1] = np.log(x) 
    return result 

def using_concat(x): 
    x = np.asarray(x) 
    return np.concatenate([x, np.log(x)], axis=-1).reshape(x.shape+(2,), order='F') 

def using_stack(x): 
    x = np.asarray(x) 
    return np.stack([x, np.log(x)], axis=x.ndim) 

def using_ufunc(x): 
    return np.array([x, np.log(x)]) 
using_ufunc = np.vectorize(using_ufunc, otypes=[np.ndarray]) 

tests = [np.arange(600), 
     np.arange(600).reshape(20,30), 
     np.arange(960).reshape(8,15,8)] 

# check that all implementations return the same result 
for x in tests: 
    assert np.allclose(using_empty(x), using_concat(x)) 
    assert np.allclose(using_empty(x), using_stack(x)) 


timing = [] 
funcs = ['using_empty', 'using_concat', 'using_stack', 'using_ufunc'] 
for test, func in IT.product(tests, funcs): 
    timing.append(timeit.timeit(
     '{}(test)'.format(func), 
     setup='from __main__ import test, {}'.format(func), number=1000)) 

timing = pd.DataFrame(np.array(timing).reshape(-1, len(funcs)), columns=funcs) 
print(timing) 

利回り、私のマシン上で次はtimeit結果:

using_empty using_concat using_stack using_ufunc 
0  0.024754  0.025182  0.030244  2.414580 
1  0.025766  0.027692  0.031970  2.408344 
2  0.037502  0.039644  0.044032  3.907487 

のでusing_emptyは(testsに適用されるテストオプションの)最速です。 np.stackが正確に何をしたいないこと

注意は、そう

np.stack([x, np.log(x)], axis=x.ndim) 

合理的にきれいに見えるが、それはまた、試験した3つのオプションの最も遅いです。

In [236]: x = np.arange(6) 

In [237]: using_ufunc(x) 
Out[237]: 
array([array([ 0., -inf]), array([ 1., 0.]), 
     array([ 2.  , 0.69314718]), 
     array([ 3.  , 1.09861229]), 
     array([ 4.  , 1.38629436]), array([ 5.  , 1.60943791])], dtype=object) 

所望の結果と同じではない:

Iが好き
In [240]: using_empty(x) 
Out[240]: 
array([[ 0.  ,  -inf], 
     [ 1.  , 0.  ], 
     [ 2.  , 0.69314718], 
     [ 3.  , 1.09861229], 
     [ 4.  , 1.38629436], 
     [ 5.  , 1.60943791]]) 

In [238]: using_ufunc(x).shape 
Out[238]: (6,) 

In [239]: using_empty(x).shape 
Out[239]: (6, 2) 
+0

'スタックに沿って非常に遅いことと、using_ufuncオブジェクトDTYPEの配列を返す


注'最高です。私は通常、スピードのためにPythonコードを最適化しません:) –

+0

これを行う別の方法として '@ ufunc'デコレータを追加してもよろしいですか? –

+0

私は '@ ufunc'デコレータに精通していません。 [this](https://mail.python.org/pipermail/python-dev/2013-June/126864.html)を参照していますか? – unutbu

関連する問題