質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.00%

  • Python

    5547questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • NumPy

    320questions

    NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。

ndarrayのufuncの引数にリストを渡して利用したい

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 391

yoh_chan

score 3

前提・実現したいこと

Pythonで、Numpyのfrompyfuncを利用してifを含む処理を配列に適用したいと考えています。
その処理の中で、引数の一つであるリストの要素を参照したいのですが、ufuncにすることによって、ブロードキャストの際にエラーが出ます。

以下の例ですと、引数のリストをそれぞれの要素に持つ(3,4)型の配列になって欲しいのですが、(当然ながら)リスト自体をブロードキャストしようとして失敗しているという状況です。

処理が遅いと聞くのでfor文で回すのは避けたいと思っているのですが、やはりfor文で処理するしかないでしょうか。お知恵をお借りしたいです。


2017-09-19追記
実際のリスト(または辞書)はデータベースから取得したパラメータの一覧であり、数十~数百程度の要素をもつテーブルで、配列の要素の値を受けて異なるインデックスを参照する必要があります。テーブルのデータなのでリストではなくndarrayであっても構わないのですが、いずれにしてもブロードキャストで失敗します。


該当のソースコード

import numpy as np


# ufunc化したい関数の定義
def hoge(a, list_b):
    if a % 2 == 0:  # 偶数
        x = a * list_b[0]
    else:  # 奇数
        x = a * list_b[1]
    return x


# ufunc化
uf_hoge = np.frompyfunc(hoge, 2, 1, dtype=int)

# 変数の定義
a = np.arange(12).reshape(3,4)
list_b = [10, -10]

# 処理
res = uf_hoge(a,list_b)

発生している問題・エラーメッセージ

ValueError
Traceback (most recent call last)
<ipython-input-14-c2794e861f7f> in <module>()
----> 1 uf_hoge(a,list_b)

ValueError: operands could not be broadcast together with shapes (3,4) (2,)

補足情報(言語/FW/ツール等のバージョンなど)

Python 2.7.5
Numpy 1.12.1

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

引数にリストを渡すのをやめて、スカラー値を2つ渡すようにするという方法では駄目でしょうか?

import numpy as np

def hoge(a, b0, b1):
    if a % 2 == 0:
        x = a * b0
    else:
        x = a * b1
    return x

a = np.arange(12).reshape(3,4)
uf_hoge = np.frompyfunc(hoge, 3, 1, dtype=int)
res = uf_hoge(a,*list_b)

あと、この程度の関数であれば、numpy.frompyfunc()ではなくnumpy.where()で書き換えた方が簡単な気がします。

import numpy as np

a = np.arange(12).reshape(3,4)
list_b = [10, -10]
res = np.where(a % 2 == 0, a * list_b[0] ,a * list_b[1])

【補足】
lambdaで引数をバインドした例

import numpy as np

def hoge(a, list_b):
    if a % 2 == 0:  # 偶数
        x = a * list_b[0]
    else:  # 奇数
        x = a * list_b[1]
    return x


# 変数の定義
a = np.arange(12).reshape(3,4)
param_b = [10, -10]
param_c = [100, -100]
param_d = [1000, -1000]

# param_b を引数にした関数をvectorize
uf_hoge_b = np.vectorize(lambda a: hoge(a, param_b))

# param_c を引数にした関数をvectorize
uf_hoge_c = np.vectorize(lambda a: hoge(a, param_c))

# param_d を引数にした関数をvectorize
uf_hoge_d = np.vectorize(lambda a: hoge(a, param_d))


# 処理
print(uf_hoge_b(a))
print(uf_hoge_c(a))
print(uf_hoge_d(a))

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/09/19 19:07

    ご回答いただき、ありがとうございます。情報が不十分で申し訳ありません。

    例示したものは極めて簡略化しているのですが、実際のリスト(または辞書)はデータベースから取得したパラメータの一覧であり、数十~数百程度の要素をもつテーブルで、配列の要素の値を受けて異なるインデックスを参照する必要があります。
    一つの関数に対して引数として与えるリスト(これは複数の場合もあります)のサイズはそれぞれ決まっているので、それらを全て分解してスカラー値として与えることも可能ではありますが、与えるパラメータ数と条件分岐が非常に多くなってしまうので避けたいところです。

    当然、配列の要素全てに同一のリストを格納するというのは不自然なので、可能ならリストそのものをufunc内で利用できればよいのですが、引数は全て自動的にブロードキャストされてしまうので難儀しています。
    配列の値に応じて処理を条件分岐する方法がufunc以外にもあればよいのですが、、、

    キャンセル

  • 2017/09/19 19:50

    そういうことなのですね・。失礼しました。
    ジャストアイデアなのですが、そのパラメータ群を frompyfunc の第2引数に渡すことを諦めて、一旦 lambda 関数などでバインドした後に ベクトル関数化するというのはいかがでしょうか。(サンプルを追加しました。)
    パラメータ毎に関数を作らなければならない気持ち悪さは残りますけれど。

    キャンセル

  • 2017/09/20 21:17

    lambda関数をそのような形で使うなんて、まったく思いつきもしないことでした…ありがとうございます。

    ただ、違う着目点ですが、補足いただいたコードを眺めていてnp.vectorizeも使えるんだったなあ、と思って調べてみたら、こちらにはexcludedというドンピシャなオプションがあることがわかりました。
    提案いただいた解法ではありませんが、おかげさまでひとまず望む結果を得ることができました。ありがとうございます。

    関数の中には出力が複数になるものもあるので、これをどうするかが次の格闘すべき問題になりそうですが…^^;

    キャンセル

0

いただいた示唆をもとに、自己解決しました。

np.vectorize()にはexcludedオプションでブロードキャストを回避できるため、これを利用することで期待する挙動を得ることができました。

import numpy as np


# ufunc化したい関数の定義
def hoge(a, list_b):
    if a % 2 == 0:  # 偶数
        x = a * list_b[0]
    else:  # 奇数
        x = a * list_b[1]
    return x


# vectorize(ブロードキャスト除外パラメータをインデックスで指定)
uf_hoge = np.vectorize(hoge, excluded=[1])

# 変数の定義
a = np.arange(12).reshape(3,4)
list_b = [10, -10]

# 処理
res = uf_hoge(a,list_b)
print(res)

結果

[[   0  -10   20  -30]
 [  40  -50   60  -70]
 [  80  -90  100 -110]]

(ただ、戻り値が複数ある関数の場合は適用できませんが…)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 91.00%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    乱数をfloat32に変換する方法

    以下で発生させた乱数とデータセットをfloat32に変換するにはどうしたら良いでしょうか? import numpy as np M = 1000 N = 3072 n =

  • 受付中

    python(predict)の使い方に関して

    前提・実現したいこと ここに質問したいことを詳細に書いてください (例)PHP(CakePHP)で●●なシステムを作っています。 ■■な機能を実装中に以下のエラーメッセージが発生し

  • 解決済

    cythonでの型の付け方

    cythonのpyxファイルに型つけをしたいです import numpy as np def gaussian(x, mean, cov): A = 1. / ((

  • 解決済

    cythonの型定義

    cythonファイルに型を定義したいです もともとのpyxファイルと 自分で型を定義したときのコードをのせます gamma1.pyx from math import exp

  • 解決済

    pythonのスライスについて

    a = b[:,0] このようなコードがあったとき、どのようなことがおこなわれますか? bはこのコードがなりたつ何かだとすると なにだったら成り立ちますか? すみません、間

  • 解決済

    python3で複数のarrayを一つにまとめる方法

    前提・実現したいこと 今,ひとつの変数 A に複数のarrayが格納されています. これを一つのarrayに直したいのですが方法がわかりません. 発生している問題・エラーメッセ

  • 解決済

    Pythonのリスト内の要素の数を数えるプログラム

    a =[ 0.1 0. 0. 0. 0. 0. 0.9 0. 0.2 0. 0.3 0. 0. 0.1 0. 0. 0.

  • 解決済

    pythonのリストに付いての質問

    pythonのリストに付いての質問です。 文字列が1500個入っているリストがあります。先頭から0,1番目をそれぞれ変数x,yに入れていき2番めを抜かして3,4をx,yに追加。5を

同じタグがついた質問を見る

  • Python

    5547questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • NumPy

    320questions

    NumPyはPythonのプログラミング言語の科学的と数学的なコンピューティングに関する拡張モジュールです。