2

したがって、基本的に私の質問は「zip」(またはizip)に関連しており、この質問は以前に尋ねられました....

反復ごとに各リストから1つの要素を取得して、2つのリストを反復処理するより良い方法はありますか?

2 つの変数がある場合、それらは長さ n の値の 1 次元配列であるか、単一の値である場合、それらをループして n 値が返されるようにするにはどうすればよいですか。

「zip」のようなものは、私が望むことを行います-単一の値と配列を渡すと文句を言うことを除いて。

私が目指しているものの例を以下に示します-基本的に、Pythonよりも効率的な計算を行うac関数があります。いくつかのnumpy関数のように動作させたい-配列とスカラーの混合物を問題なく扱うので、そのためのpythonラッパーを書きました。ただし、私が言うように、「zip」は失敗します。原則として、入力 s のいくつかのテストを行い、スカラーと配列のバリエーションごとに異なるステートメントを作成できると思いますが、python にはもっと賢いものが必要なようです.... ;) 何かアドバイスはありますか?

"""
    Example of zip problems.
"""

import numpy as np
import time

def cfun(a, b) :
    """
        Pretending to be c function which doesn't deal with arrays
    """
    if not np.isscalar(a)   or  not np.isscalar(b)  :

        raise Exception('c is freaking out')
    else :

        return a+b

def pyfun(a, b) :
    """
        Python Wrappper - to deal with arrays input
    """

    if not np.isscalar(a)   or  not np.isscalar(b) :
        return np.array([cfun(a_i,b_i) for a_i, b_i in zip(a,b)])

    else :

        return cfun(a, b)

    return cfun(a,b)


a = np.array([1,2])
b= np.array([1,2])
print pyfun(a, b)

a = [1,2]
b = 1
print pyfun(a, b)

編集 :

みんなの提案に感謝します。解決策として np.braodcast を使用する必要があると思います-私の観点からは最も単純に思えるので.....

4

3 に答える 3

1

ブロードキャストを強制したい場合は、 を使用できますnumpy.lib.stride_tricks.broadcast_arrays。あなたの再利用cfun

def pyfun(a, b) :
    if not (np.isscalar(a) and np.isscalar(b)) :
        a_bcast, b_bcast = np.lib.stride_tricks.broadcast_arrays(a, b)
        return np.array([cfun(j, k) for j, k in zip(a_bcast, b_bcast)])
    return cfun(a, b)

そしていま:

>>> pyfun(5, 6)
11
>>> pyfun(5, [6, 7, 8])
array([11, 12, 13])
>>> pyfun([3, 4, 5], [6, 7, 8])
array([ 9, 11, 13])

特定のアプリケーションでは、関数がまだ Python ループで実行されているため、Rob の純粋な Python に勝る利点はおそらくありません。

于 2013-03-01T23:03:30.153 に答える
0

各引数をシーケンスに最適に変換するデコレータが役立つ場合があります。これは通常のpython(numpyではない)バージョンです:

# TESTED
def listify(f):
  def dolistify(*args):
    from collections import Iterable
    return f(*(a if isinstance(a, Iterable) else (a,) for a in args))
  return dolistify

@listify
def foo(a,b):
  print a, b

foo( (1,2), (3,4) )
foo( 1, [3,4] )
foo( 1, 2 )

したがって、あなたの例ではnot np.isscalar、述語およびnp.array修飾子として使用する必要があります。デコレーターのため、pyfun常に配列を受け取ります。

#UNTESTED
def listify(f):
  def dolistify(*args):
    from collections import Iterable
    return f(*(np.array([a]) if np.isscalar(a) else a for a in args))
  return dolistify

@listify
def pyfun(a, b) :
    """
        Python Wrappper - to deal with arrays input
    """

    return np.array([cfun(a_i,b_i) for a_i, b_i in zip(a,b)])

または、同じアイデアをzip次のように適用することもできます。

#UNTESTED
def MyZip(*args):
  return zip(np.array([a]) if np.isscalar(a) else a for a in args)

def pyfun(a, b) :
    """
        Python Wrappper - to deal with arrays input
    """

    return np.array([cfun(a_i,b_i) for a_i, b_i in MyZip(a,b)])
于 2013-03-01T22:51:49.300 に答える