裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

Julia で Python プログラムを動かす--その2

2021年09月12日 | ブログラミング

なにはともあれ,最初に using PyCall 追記あり(2021/09/13)

using PyCall

Python のパッケージの import は以下のようにする

math = pyimport("math") # import math as math に相当

パッケージ中の関数は Python で記述するそのまま

math.sin(math.pi / 4)  # 0.7071067811865475 # Python の math パッケージの sin と π
sin(pi / 4)            # 0.7071067811865475 Julia の sin 関数と π

np = pyimport("numpy") # import numpy as np に相当
np.arcsin(0.5)
arcsin(0.5)        # UndefVarError: arcsin not defined
                      
# Julia には arcsin という関数はないのでエラーになる
asin(0.5)              # 0.5235987755982989 # Julia では asin という名前
math.asin(0.5)         # 0.5235987755982988 # Python の math パッケージでは asin という名前

matplotlib.pyplot での描画

plt = pyimport("matplotlib.pyplot")
x = range(0;stop=2*pi,length=1000); # Julia で定義
y = sin.(3*x + 4*cos.(2*x));        # Julia で定義
plt.plot(x, y, color="red", linewidth=2.0, linestyle="--")
plt.show()

上のようにして PyPlot するのではなく,Julia で以下のようにすれば同じようにプロットできる(PyCall は明示的には使わない)。

using PyPlot
x = range(0;stop=2*pi,length=1000); # Julia で定義
y = sin.(3*x + 4*cos.(2*x));        # Julia で定義
plot(x, y, color="red", linewidth=2.0, linestyle="--")

あるライブラリをインポートしたときにエラーになるときの対処法

so = pyimport("scipy.optimize")

これを実行したとき,
    PyError (PyImport_ImportModule
    The Python package scipy.optimize could not be imported by pyimport.
と言われた場合は,scipy.optimize がないということである。
いつも使っている Python には scipy.optimize はあるのに?という場合は,エラーメッセージに示されているサジェスチョンに従う必要がある。

Julia が想定する Python は Conda.jl パッケージ でインストールされる最小限の Python(minimal Python distribution)である。そこには scipy.optimize はないということである。

いくつかある対処法のどれを採用するか迷うかも知れないが,もっとも適切なのは,通常使っている Python を使うことであろうか。その場合には,以下の 3 行に示すように PyCall を再ビルドする必要がある(Python のバージョンが変わった場合には常に再ビルドした方が良い)。

# ENV["PYTHON"] = "/usr/local/bin/python3"
# using Pkg
# Pkg.build("PyCall")

なお,元の Julia 依存の Python を使う場合は,1行目を ENV["PYTHON"] = "" として PyCall を再ビルドすればよい。

また,再ビルドした場合は,一度 Julia を終了し,再度 Julia を立ち上げる必要がある。

なにはともあれ,Python の scipy.optimize がインポートできれば,そのなかの newton 関数を使えると言うことである。

so.newton(x -> cos(x) - x, 1) # 0.7390851332151607

pycall で Python の関数を呼ぶ

pycall(func::PyObject, returntype::Type, args...)
@pycall func(args...)::returntype

math.sqrt(3.0)
pycall(math.sqrt, PyAny, 3.0)   # 1.7320508075688772
pycall(math.sqrt, Float64, 3.0) # 1.7320508075688772
@pycall math.sqrt(3.0)::Float64 # 1.7320508075688772

using Random; Random.seed!(12345)
x = randn(100);
sum(x)                   # 0.9821131440360702 Julia の sum 関数
pycall(np.sum, PyAny, x) # 0.9821131440360702 
np.sum(x)                # 0.9821131440360702

前の記事にも書いたが,py"...", py"""...""" で ... の部分に書かれた Python プログラムを実行できる。

using PyCall

py"""
import numpy as np
def f(x):
    return x**2
"""

py"f(5)" # 25

py"\"hello\"" # py"print(\"hello\")"

"""...""" は結果を返さない(後述)

py"print(\"hello\")"

py"""
print(9)
"""

Julia 中での変数などを PyCall で参照するのは「$変数名」でできる(RCall と同じ)。
また,PyCall の結果も,Julia の変数に代入できる。

using PyCall

以下の例は,Julia の配列 [1,2,3] を Python の sum 関数で和をとる例である。

py"sum($([1,2,3]))" # 6

配列 x を $x で参照する。

x = [1, 2, 3]
py"sum($x)" # 6

Julia の文字列変数は $y, $$y のようにして使用できる。

y = "1+2+3"

$y は文字列そのまま使用される

py"$y" # "1+2+3"

$$y は文字列を評価して使用される

py"$$y" # 6

直接文字列を記載する場合は \ でエスケープする。

py"$$(\"1+2+3\")" # 6

以下の例で,sqrt(8)+1 は Python の式として評価される。従って sqrt() という関数はないのでエラーになる。

z = "sqrt(8)+1"
py"$$z" # PyError

math パッケージをインポートしてもエラーになる。結局,解決法はまだわからない。

math = pyimport("math")

当然,以下は正しく実行される。

math.sqrt(8)+1 # 3.8284271247461903

z = "math.sqrt(8)+1" # "math.sqrt(8)+1"
py"$z" # "math.sqrt(8)+1"
py"$$z" # PyError

引き渡される文字列は「Python の式」であることに注意が必要。

以下は「2 の 4 乗から 3 を引く」つまり結果として 13 を得る。

z = "2**4-3"
py"$$z" # 13

以下は「2 と 4 のビット和から 3 を引く」。つまり 0b010 と 0b100 のビット和 0b110 = 6 から 3 を引くので,結果は 3 になる。

z = "2^4-3"
py"$$z" # 3

前にも述べたが,"""...""" は結果を返さない。

py"""
x = 2
y = 3
x ** y
"""

Julia に結果を返す変数を global 指定すると後で引用できる。

py"""
global g
x = 2
y = 3
g = x ** y
"""

py"g"     # 8
a = py"g" # 8
a         # 8

 

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« 家紋シリーズ 雁金(1) 丸に... | トップ | Julia の小ネタ--035 文字列... »
最新の画像もっと見る

コメントを投稿

ブログラミング」カテゴリの最新記事