PythonCall dan RCall

Menjembatani Julia dengan ekosistem Python dan R melalui PythonCall.jl dan RCall.jl.

Daftar isi

Dua ekosistem komputasi terbesar, yaitu Python dan R, dapat diakses langsung dari Julia melalui package PythonCall.jl dan RCall.jl. Keduanya memuat penerjemah bahasa tujuan ke dalam proses Julia, sehingga fungsi Python atau R dapat dipanggil tanpa menyalin data melalui berkas perantara. Topik ini membahas pemanggilan fungsi Python, konversi tipe dua arah, bentuk pemakaian RCall.jl, serta kesalahan yang lazim terjadi saat menjembatani dua bahasa.

Memanggil fungsi Python#

Package PythonCall.jl menyematkan penerjemah Python ke dalam proses Julia melalui libpython, sehingga modul Python dimuat dan dipanggil dari REPL maupun skrip Julia. Modul diperoleh dengan pyimport, dan fungsi di dalamnya dipanggil dengan tanda titik seperti biasa. Contoh berikut memuat modul math bawaan Python, lalu memanggil sqrt dan membaca konstanta pi.

julia Contoh: memuat modul math Python
using PythonCall

m = pyimport("math")
println(m.sqrt(2.0))
println(pyconvert(Float64, m.sqrt(2.0)))
println(pyconvert(Float64, m.pi))
text Keluaran
1.4142135623730951
1.4142135623730951
3.141592653589793

Hasil m.sqrt(2.0) bertipe Py, yaitu wadah yang merujuk objek Python tanpa menyalinnya, dan pencetakannya menampilkan bentuk Python itu sendiri. Fungsi pyconvert mengubah objek tersebut menjadi nilai Julia dengan tipe yang diminta, sehingga nilai tersebut kemudian dapat dipakai dalam perhitungan Julia seperti biasa.

Objek Python yang dirujuk tetap hidup selama wadah Py dipakai. PythonCall melepas rujukan Python secara otomatis saat wadah tersebut tidak lagi terjangkau, sehingga penghitungan referensi Python tetap konsisten tanpa pengelolaan manual. Pemanggilan metode dan pembacaan atribut dilakukan langsung pada Py dengan tanda titik, sehingga m.sqrt(2.0) benar-benar mengeksekusi fungsi milik Python, bukan tiruannya. Bila hasilnya diperlukan dalam perhitungan Julia yang panjang, konversi tetap dilakukan agar tipe hasilnya stabil.

Konversi tipe antara Julia dan Python#

Nilai Julia yang menjadi argumen pemanggilan fungsi Python dikonversi otomatis untuk tipe-tipe dasar, sehingga vektor Julia dapat langsung diterima fungsi Python. Arah sebaliknya dilakukan secara eksplisit melalui pyconvert, karena tipe Julia tujuan harus dipilih sendiri. Pembentukan objek Python dari nilai Julia juga tersedia dalam bentuk fungsi seperti pylist dan pydict.

julia Contoh: konversi dua arah dengan modul statistics
using PythonCall

st = pyimport("statistics")
nilai = [2.0, 4.0, 4.0, 8.0]
println(pyconvert(Float64, st.mean(nilai)))

daftar = pylist([1, 2, 3])
println(daftar)
println(pyconvert(Vector{Int}, daftar))
println(pyconvert(Int, daftar[1]))
text Keluaran
4.5
[1, 2, 3]
[1, 2, 3]
2

Baris kedua dan ketiga menampilkan tulisan yang sama, tetapi isinya berbeda. Baris kedua masih berupa PyList, yaitu rujukan ke list Python, sedangkan baris ketiga sudah menjadi Vector{Int} milik Julia. Pemanggilan daftar[1] pada Py mengikuti indeks Python yang dimulai dari nol, sehingga yang terbaca adalah elemen kedua, yaitu 2.

Tabel berikut meringkas konversi yang paling sering dipakai.

Nilai JuliaMenuju PythonNilai PythonMenuju Julia
Int, Float64otomatis sebagai argumenint, floatpyconvert(Int, p), pyconvert(Float64, p)
Stringotomatis sebagai argumenstrpyconvert(String, p)
Vectorpylist(v) atau otomatislistpyconvert(Vector{T}, p)
Dictpydict(d)dictpyconvert(Dict, p)

Arah konversi yang eksplisit membuat kegagalan konversi terdeteksi di tempat yang jelas. Pemanggilan pyconvert atas objek yang tidak cocok dengan tipe tujuan melempar error dengan pesan cannot convert this Python 'str' to a Julia 'Int64', sehingga pilihan tipe yang salah langsung terlihat. Kebiasaan yang sehat adalah memilih tipe tujuan paling sempit yang memadai, misalnya Vector{Float64} alih-alih Vector{Any}.

RCall.jl untuk ekosistem R#

Package RCall.jl bekerja dengan pola yang sama, yaitu memuat penerjemah R ke dalam proses Julia. Prasyaratnya berbeda, yaitu R harus sudah terpasang pada sistem karena RCall.jl tidak menyediakan R sendiri. Variabel dipindahkan dari Julia ke R dengan makro @rput dan kembali dengan @rget, sedangkan ekspresi R ditulis di dalam string makro R"...".

julia Contoh: bentuk pemakaian RCall.jl
# tidak-dijalankan
# R tidak tersedia di sandbox, sehingga contoh ini hanya menampilkan bentuknya.
using RCall

x = [2.0, 4.0, 4.0, 8.0]
@rput x
rata = rcopy(R"mean(x)")
println(rata)

Makro @rput x membuat objek x tersedia di lingkungan R global, string makro R"mean(x)" mengevaluasi panggilan fungsi mean milik R atas data tersebut, dan rcopy mengonversi hasil R menjadi nilai Julia. Konversi sebaliknya memakai RObject, yaitu wadah yang membungkus nilai Julia menjadi objek R. Untuk data tabular, DataFrame Julia dan data.frame R saling dikonversi melalui rcopy dan RObject yang sama.

Interpolasi nilai Julia ke dalam ekspresi R ditulis dengan tanda dolar di dalam string makro, misalnya R"mean($x)", sehingga nilai yang sudah ada di Julia tidak perlu disalin manual terlebih dahulu. Fungsi rcopy mengembalikan tipe Julia yang wajar untuk objek R yang diberikan, misalnya vektor numerik R menjadi Vector{Float64}. Makro @rput dan @rget menerima banyak variabel sekaligus, sehingga pemindahan sekumpulan data hanya memerlukan satu baris.

Kesalahan umum#

Kesalahan pertama adalah membiarkan perhitungan panjang bekerja pada objek Py alih-alih nilai Julia yang sudah dikonversi. Setiap operasi pada Py melewati jembatan antarbahasa, sehingga konversi sebaiknya dilakukan sekali di awal dan hasilnya disimpan sebagai array Julia.

Kesalahan kedua adalah menganggap pencetakan sama dengan konversi. Objek Py yang dicetak menampilkan bentuk Pythonnya, tetapi tipenya tetap Py hingga pyconvert dipanggil, sehingga nilai itu belum dapat diterima fungsi Julia yang menuntut tipe konkret.

Kesalahan ketiga berkaitan dengan prasyarat. PythonCall.jl mengelola Python miliknya melalui CondaPkg, sedangkan RCall.jl menuntut R yang terpasang di sistem. Apabila pyimport gagal menemukan sebuah modul, modul Python tambahan dinyatakan lebih dahulu sebagai dependensi CondaPkg, misalnya melalui CondaPkg.add("numpy"), sehingga pemuatan berikutnya menemukan modul tersebut.

Ringkasan#

  • PythonCall.jl memuat penerjemah Python dalam proses Julia, dengan pyimport untuk memuat modul dan Py sebagai wadah objek Python.
  • Konversi Julia ke Python berlangsung otomatis untuk tipe dasar, sedangkan arah sebaliknya eksplisit melalui pyconvert.
  • RCall.jl memuat penerjemah R, memindahkan variabel dengan @rput dan @rget, serta mengevaluasi ekspresi R melalui string makro R"...".
  • Indeks objek Py mengikuti konvensi Python, dan objek Py perlu dikonversi sebelum dipakai dalam perhitungan Julia.

Referensi#